728x90
✳ MemberController 만들기
// @RequestMapping : 요청 주소에 맞는 클래스/메소드 연결
// @RequestMapping("요청 주소")
// -> GET / POST 구분 X(모두 받음, 주소만 맞으면 연결)
// @RequestMapping(value="요청 주소", method=RequestMethod.GET/POST)
// -> GET / POST 방식을 구분
@Controller // 요청, 응답 클래스 + bean 등록(Spring이 관리하는 객체)
@RequestMapping("/member") // 공통된 주소 앞부분 작성
// member로 시작하는 요청은 해당 컨트롤러에서 처리
@SessionAttributes("loginMember") // Model의 이름(key)를 적으면 session으로 추가 (여러개라면 배열형태로 작성 {"loginMember","test","pw"}
public class MemberController {
// 등록된 Bean 중에서 필드와 타입이 일치하는 Bean을 주입
// -> MemberService를 구현한 MemberServiceImpl의 Bean을 주입
@Autowired
private MemberService service;
/**
* 로그인 요청 처리(찐)
* @return 메인페이지 redirect 주소
*/
@PostMapping("/login")
public String login(Member inputMember, Model model
, @RequestHeader(value = "referer") String referer
, @RequestParam(value = "saveId", required = false) String saveId
, HttpServletResponse resp
, RedirectAttributes ra) {
// Member inputMember : 커맨드 객체(필드에 파라미터 담겨있음)
// @RequestHeader(value="referer") String referer
// -> 요청 HTTP header에서 "referer" (이전주소) 값을 얻어와
// 매개변수 String referer에 저장
// Model : 데이터 전달 용 객체
// - 데이터를 K : V 형식으로 담아서 전달
// - 기본적으로 request scope
// - @SessionAttributes 어노테이션 함께 사용 시 Session scope
// @RequestParam(value="saveId") String saveId
// -> name 속성 값이 "saveId"인 파라미터를 전달 받아 저장
// (주의) required 속성 미 작성 시 기본 값 true -> 파라미터가 전달 되지 않는 경우 주의
// -> required=false : 필수 아님 (null 허용)
// HttpServletResponse resp : 서버 -> 클라이언트 응답 방법을 가지고 있는 객체
// 로그인 서비스 호출
Member loginMember = service.login(inputMember);
System.out.println(inputMember);
// DB 조회 결과 확인
// System.out.println(loginMember);
// 로그인 결과에 따라 리다이렉트 경로를 다르게 지정
String path = "redirect:";
if (loginMember != null) { // 로그인 성공 시 메인페이지로 리다이렉트
path += "/";
// Session에 로그인한 회원 정보 추가
// Servlet -> HttpSession.setAttribute(key,value)
// Spring -> Model + @SessionAttributes
// 1) model에 로그인한 회원 정보 추가
model.addAttribute("loginMember", loginMember);
// -> 현재는 request scope
// 2) 클래스 위에 @SessionAttributes 추가
// -> session scope로 변경
// -------------------- 아이디 저장 --------------------
/*
* Cookie란 ? - 클라이언트 측 (브라우저)에서 관리하는 파일
*
* - 쿠키 파일에 등록된 주소 요청 시 마다 자동으로 요청에 첨부되어 서버로 전달
*
* - 서버로 전달 된 쿠키에 값 추가, 수정, 삭제 등을 진행 한 후 다시 클라이언트에게 반환
*
* Session - 서버가 클라이언트의 정보를 저장하고 있다.
*
* ! 차이점 ! 세션 = 서버가 직접 관리! 쿠키 = 클라이언트 직접 관리!
**/
// 쿠키 생성 (해당 쿠키에 담을 데이터를 K:V로 지정)
Cookie cookie = new Cookie("saveId", loginMember.getMemberEmail());
if (saveId != null) { // 체크 되었을 때
// 한 달(30일) 동안 유지되는 쿠키 생성 (초 단위 지정)
cookie.setMaxAge(60 * 60 * 24 * 30);
} else { // 체크 안되었을 때
// 0초 동안 유지되는 쿠키 생성
// -> 기존 쿠키를 삭제
cookie.setMaxAge(0);
}
// 클라이언트가 어떤 요청을 할 때 쿠키가 첨부될지 경로(주소)를 지정
cookie.setPath("/"); // localhost / 이하 모든 주소
// ex) / , /member/login, /member/logout 등
// 모든 요청에 쿠키 첨부
resp.addCookie(cookie);
// 응답 객체 (HTTPServletResponse)를 이용해서
// 만들어진 쿠키를 클라이언트에게 전달
} else { // 로그인 실패 시
path += referer; // HTTP Header - referer (이전주소)
// Servlet -> HttpServletRequest.getHearder("referer")
/* redirect(재요청)시
* 기존 요청(request)이 사라지고
* 새로운 요청 (request)을 만들게 되어
* redirect된 페이지에서는 이전 요청이 유지 되지 않는다!
* -> 유지 하고 싶으면 어쩔 수 없이 Sesion을 이용
*
* [Spring]
* 이런 상황을 해결하기 위한 객체
* RedirectAttributes를 제공
*
* RedirectAttributes
* : 리다이렉트 시 데이터를 request scope로 전달 할 수 있게 하는 객체
*
* 응답 전 : request scope
* 응답 중 : session scope로 잠시 이동
* 응답 완료 : request scope 복귀
*
* **/
// addFlashAttribute
ra.addFlashAttribute("message","아이디 또는 비밀번호가 일치하지 않습니다.");
}
return path;
}
// 로그아웃
@GetMapping("/logout")
public String logout(SessionStatus status, HttpSession session) {
// SessionStatus : 세션 상태를 관리하는 객체
// 세션 무효화
// Servlet -> HttpSession.invalidate()
// Spring
// 1) HttpSession을 이용한 경우
// -> HttpSession.invalidate()
// 2) Model + @SessionAttributes 이용한 경우
// -> SessionStatus.setComplete()
status.setComplete();
// session.invalidate(); // 세션 무효화
return "redirect:/";
}
// 로그인 전용 화면 이동
@GetMapping("/login")
public String login() {
return "member/login";
}
// 회원 가입 페이지 이동
@GetMapping("/signUp")
public String signUp() {
// /WEB-INF/views/member/signUp.jsp forward(요청위임)
// viewResovelr가 prefix, suffix를 리턴 값 앞,뒤에 붙임
return "member/signUp";
}
// 회원 가입 진행
@PostMapping("/signUp")
public String signUp(Member inputMember
,/*@RequestParam("memberAddress")*/ String[] memberAddress
,RedirectAttributes ra) {
// ------------ 매개 변수 설명 ------------
// Member inputMember : 커멘드 객체 (제출된 파라미터가 저장된 객체)
// String[] memberAddress :
// input name = "memberAddress" 3개가 저장된 배열
// RedirectAttributes ra :
// 리다이렉트 시 데이터를 request scope로 전달하는 객체
// -------------------------------------
// 12345^^^서울시^^^2층
// 주소 구분자를 , -> ^^^ 변경
//String addr = inputMember.getMemberAddress().replaceAll(",","^^^");
//inputMember.setMemberAddress(addr);
// ->클라이언트가 ,를 직접 입력하면 문제 발생 (a^^^^^^^b^^^^^^^^.. 이런식으로)
// 만약 주소를 입력하지 않은 경우(,,) null로 변경 --> db에 굳이 ,, 넣을 필요 없음
if(inputMember.getMemberAddress().equals(",,")) {
inputMember.setMemberAddress(null);
}else {
// String.join("구분자",String[])
// 배열의 요소를 하나의 문자열로 변경
// 단, 요소 사이에 "구분자"추가
String addr = String.join("^^^", memberAddress);
inputMember.setMemberAddress(addr);
}
//회원 가입 서비스 호출
int result = service.signUp(inputMember);
// 가입 성공 여부에 따라 주소 결정
String path = "redirect:";
String message = null;
if(result>0) { //가입 성공 시 메인페이지
path += "/";
message = inputMember.getMemberNickname()+"님의 가입을 환영합니다.";
}else { // 가입 실패 시 회원가입 페이지
//path += "/member/signUp"; // 절대경로
path += "signUp"; // 상대경로
message = "회원 가입 실패 ! ";
}
// 리다이렉트 시 session에 잠깐 올라갔다 내려오도록 세팅!
ra.addFlashAttribute("message",message);
return path;
}
/* 스프링 예외 처리 방법 (3종류, 우선순위, 중복사용)
*
* 1순위 : 메소드 단위로 처리
* -> try-catch / throws
*
* 2순위 : 클래스 단위로 처리
* -> @ExceptionHandler
*
* 3순위 : 프로그래밍 단위(전역)처리
* -> @ControllerAdvice
* **/
// 현재 클래스에서 발생하는 모든 예외를 모아서 처리
// @ExceptionHandler(Exception.class)
public String exceptionHandler(Exception e, Model model) {
// Exception e : 예외 정보를 담고 있는 객체
// Model model : 데이터 전달용 객체 (request scope가 기본)
e.printStackTrace(); // 예외 내용/ 발생 메소드
model.addAttribute("e",e);
// foward 진행
// -> View Resolver의 prefix,suffix를 붙여 JSP 경로로 만듦
return "common/error";
}
}
✳ MemberService interface 만들기
🌝 사용이유 🌝
1. 프로젝트 규칙성을 부여하기 위해서
2. 클래스간의 결합도를 약화시키기 위해서 (객체 지향적 설계)
3. Spring AOP 사용을 위해서
public interface MemberService {
/** 로그인 서비스
* @param inputMember (email, pw)
* @return email, pw가 일치하는 회원 정보 또는 null
*/
Member login(Member inputMember);
}
✳ MemberServiceImpl class 만들기
package edu.kh.project.member.model.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import edu.kh.project.member.model.dao.MemberDAO;
import edu.kh.project.member.model.dto.Member;
@Service // Service Layer
// 비지니스 로직(데이터 가공, dao 호출, 트랜잭션 제어) 처리하는 클래스라고 명시한 것
// + Bean으로 등록하는 어노테이션
public class MemberServiceImpl implements MemberService {
// @Autowired : 작성된 필드와 Bean으로 등록된 객체 중
// 타입이 일치하는 Bean을 해당 필드에
// 자동으로 주입(Injection)하는 어노테이션
// == DI(Dependency Injection, 의존성 주입)
// -> 객체를 직접 만들지 않고 Spring이 만든 객체를 주입함 (Spring에 의존)
@Autowired
private MemberDAO dao;
@Autowired // bean으로 등록된 객체 중 타입이 일치하는 객체를 DI (의존성 주입)
private BCryptPasswordEncoder bcrypt;
@Override
public Member login(Member inputMember) {
// 암호화 추가 예정
// System.out.println("암호화 확인 : " + bcrypt.encode(inputMember.getMemberPw()));
// bcrypt 암호화는 salt가 추가되기 때문에
// 계속 비밀번호가 바뀌게 되어서 DB에서 비교 불가능!
// -> 별도로 제공해 주는 matches(평문, 암호문)을 이용해 비교
// DAO 메소드 호출
Member loginMember = dao.login(inputMember);
if(loginMember != null) { // 아이디가 일치하는 회원이 조회된 경우
// 입력한 pw, 암호화된 pw 같은지 확인
// 같을 경우
if(bcrypt.matches(inputMember.getMemberPw(),
loginMember.getMemberPw())) {
// 비밀번호를 유지하지 않기 위해서 로그인 정보에서 제거
loginMember.setMemberPw(null);
} else { // 다를 경우
loginMember = null; // 로그인 실패처럼 만듦
}
}
return loginMember;
}
}
✳ MemberDAO class 만들기
package edu.kh.project.member.model.dao;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import edu.kh.project.member.model.dto.Member;
@Repository // Persistence Layer, 영속성 관련 클래스
// (파일, DB 관련 클래스) + Bean 등록(== Spring이 객체로 만들어 둔다.)
public class MemberDAO {
// SqlSessionTemplate (마이바티스 객체) DI
@Autowired // 등록된 Bean 중에서 SqlSessionTemplate 타입의 Bean을 주입
private SqlSessionTemplate sqlSession;
/** 로그인 DAO
* @param inputMember
* @return 회원 정보 또는 null
*/
public Member login(Member inputMember) {
// 마이바티스를 이용해서 1행 조회(selectOne)
// sqlSession.selectOne("namespace값.id값", 전달할 값)
// -> namespace가 일치하는 Mapper에서
// id가 일치하는 SQL 구문을 수행 후
// 결과를 1행(dto, 기본 자료형) 반환
// return sqlSession.selectOne("memberMapper.id값", 전달할 값);
return sqlSession.selectOne("memberMapper.login", inputMember);
}
}
✳ member-mapper.xml 만들기 (sql 작성하는 부분)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="memberMapper">
<!-- namespace : 공간(영역, 지역, 태그)의 이름 -->
<!-- mapper 파일 생성 시 아래 태그는 반드시 삭제!!! -->
<!-- <cache-ref namespace=""/> -->
<!--
resultMap
- SELECT 조회 결과(ResultSet) 컬럼명과
컬럼 값을 옮겨 담을 DTO의 필드명이 같지 않을 때
이를 매핑시켜 SELECT 시 자동으로 담기게 하는 역할
- 속성
type : 연결할 DTO (패키지명 + 클래스명 또는 별칭)
id : 만들어진 resultMap을 지칭할 식별명(이름)
<id> 태그 : PK 역할 커럼 - 필드 매핑
<result> 태그 : <id> 제외 나머지
-->
<resultMap type="Member" id="member_rm">
<!-- DB의 기본 키(복합키라면 여러 개 작성) -->
<id property="memberNo" column="MEMBER_NO"/>
<!-- DB의 일반 컬럼들 -->
<result property="memberEmail" column="MEMBER_EMAIL"/>
<result property="memberPw" column="MEMBER_PW"/>
<result property="memberNickname" column="MEMBER_NICKNAME"/>
<result property="memberTel" column="MEMBER_TEL"/>
<result property="memberAddress" column="MEMBER_ADDR"/>
<result property="profileImage" column="PROFILE_IMG"/>
<result property="enrollDate" column="ENROLL_DATE"/>
<result property="memberDeleteFlag" column="MEMBER_DEL_FL"/>
<result property="authority" column="AUTHORITY"/>
</resultMap>
<!--
SQL 관련 태그 속성
- parameterType : 전달받은 값의 자료형
기본 : 패키지명 + 클래스명
별칭 : Mybatis 별칭 또는 사용자 지정 별칭
- parameterMap : (ibatis 호환용이라 사용 안 함)
- resultType : select 결과를 담아서 반환할 자료형
단, DTO를 작성할 경우 '필드명 = 컬럼명'인 경우에만 사용 가능
memberNo MEMBER_NO (사용 X)
- resultMap : select 결과의 컬럼명과 결과를 저장할 DTO 필드명이 다를 경우
이를 알맞게 매핑(연결)시켜 주는 <resultMap> id 작성
-->
<!--
** 마이바티스에서 전달받은 값을 SQL에 작성하는 방법 **
#{변수명|필드명} : PreparedStatement와 유사
SQL에 값 대입 시 양쪽에 '' 붙여서 대입함
${변수명|필드명} : Statement와 유사
SQL에 값 대입 시 양쪽에 아무것도 붙이지 않음
[사용 예시]
test1 = "user01"
test2 = MEMBER_EMAIL
- MEMBER_EMAIL이 'user01'인 회원 조회
SELECT * FROM MEMBER WHERE ${test2} = #{test1}
MEMBER_EMAIL = 'user01'
-->
<select id="login" parameterType="Member" resultMap="member_rm">
SELECT MEMBER_NO, MEMBER_EMAIL, MEMBER_NICKNAME, MEMBER_PW,
MEMBER_TEL, MEMBER_ADDR, PROFILE_IMG, AUTHORITY,
TO_CHAR(ENROLL_DATE, 'YYYY"년" MM"월" DD"일" HH24"시" MI"분" SS"초"') AS ENROLL_DATE
FROM "MEMBER"
WHERE MEMBER_DEL_FL = 'N'
AND MEMBER_EMAIL = #{memberEmail}
</select>
</mapper>
✳ mybatis-config.xml 만들기 ( vo 클래스 별칭부여 / mapper 파일 위치 등록)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" >
<configuration>
<!-- SqlSessionTemplate 생성 시 적용될 설정 작성 부분 -->
<settings>
<!-- insert 또는 update에 사용되는 값 중 null이 있을 경우에 대한 설정
해당 설정이 없을 경우 -> SQL 구문에 null 포함되어 있다는 오류 발생
해당 설정이 있을 경우 -> 오류를 발생 시키지 않고 NULL 값을 컬럼에 대입
단, NOT NULL 제약조건이 없는 컬럼에만 가능함
** value 설정 시 NULL 은 반드시 대문자로 작성 (소문자 null은 오류가 발생함) ** -->
<setting name="jdbcTypeForNull" value="NULL" />
</settings>
<!-- 별칭 작성 부분 -->
<!-- VO클래스의 패키지명 + 클래스명 작성하는 것이 불편하기 때문에 짧은 별칭 부여 -->
<typeAliases>
<typeAlias type="edu.kh.project.member.model.dto.Member" alias="Member" /> <!-- 사용자 별칭 -->
</typeAliases>
<!-- mapper 파일(SQL 작성되는파일) 위치 등록 부분 -->
<mappers>
<mapper resource="/mappers/member-mapper.xml" />
</mappers>
</configuration>
✳ porm.xml 내용추가
<!-- 스프링에서 JDBC를 사용할 수 있게 하는 라이브러리 -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
<!-- 위 properties의 지정한 Spring 버전을 따라감 -->
</dependency>
<!-- Mybatis 영속성 프레임 워크 -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<!-- Spring - Mybatis 연결 모듈, 연결 역할을 하는 라이브러리 -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!-- 커넥션 풀 기능을 사용하기 위한 라이브러리 -->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.9.0</version>
</dependency>
🔑
@Service // service Layer
: 비즈니스 로직 (데이터 가공, dao 호출, 트랜잭션 제어) 처리하는 클래스라 명시
+ Bean 등록하는 어노테이션
@Autowired : 작성된 필드와 Bean으로 등록된 객체 중 타입이 일치하는 Bean을
해당 필드에 자동으로 주입(Injection)하는 어노테이션
== DI (Dependency Injection, 의존성 주입)
-> 객체를 직접 만들지 않고, Spring이 만든걸 주입함
@Repository : Persistence Layer, 영속성 관련 클래스
(파일, DB 관련 클래스) + Bean 등록 (==spring이 객체로 만들어줌)
📁 MyBatis : JDBC 프레임워크(틀)
데이터의 입력, 조회, 수정, 삭제(CRUD)를 보다 편하게 하기 위해
xml로 구조화한 Mapper 설정 파일을 통해서 JDBC를 구현한 영속성 프레임워크
-> 기존에 JDBC를 통해 구현했던
상당 부분의 코드와 파라미터 설정 및 결과 매핑을 xml 설정을 통해 쉽게 구현할 수 있게 해 준다.
📁 MyBatis 흐름
( 이전 Servelt 할때 JDBC Template을 통해 SQL을 실행했었는데, Mybatis는 전용 라이브러리를 통해 동작한다.)
📁 MyBatis 동작 구조
➰ Mybatis config 설정하기
- Config
Location : http://mybatis.org/dtd/mybatis-3-config.dtd
Key type : Public ID
Key : -//mybatis.org//DTD Config 3.0//EN
- Mapper
Location : http://mybatis.org/dtd/mybatis-3-mapper.dtd
Key type : Public ID
Key : -//mybatis.org//DTD Mapper 3.0//EN
➰ config .xml 생성
➰ mybatis - config설정 추가 ( 전체 복붙해도 상관없음 )
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" >
<configuration>
<!-- SqlSessionTemplate 생성 시 적용될 설정 작성 부분 -->
<settings>
<!-- insert 또는 update에 사용되는 값 중 null이 있을 경우에 대한 설정
해당 설정이 없을 경우 -> SQL 구문에 null 포함되어 있다는 오류 발생.
해상 설정이 있을 경우 -> 오류를 발생 시키지 않고 NULL 값을 컬럼에 대입
단, NOT NULL 제약조건이 없는 컬럼에만 가능함.
** value 설정 시 NULL 은 반드시 대문자로 작성 (소문자 null은 오류가 발생함) -->
<setting name="jdbcTypeForNull" value="NULL" />
</settings>
<!-- 별칭 작성 부분 -->
<!-- VO클래스의 패키지명 + 클래스명 작성하는 것이 불편하기 때문에 짧은 별칭 부여 -->
<typeAliases>
<typeAlias type="edu.kh.project.member.model.dto.Member" alias="Member" />
</typeAliases>
<!-- mapper 파일(SQL 작성되는파일) 위치 등록 부분 -->
<mappers>
<mapper resource="/mappers/member-mapper.xml" />
</mappers>
</configuration>
➰ root-context.xml 설정 추가
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<!-- 프로젝트 전반적으로 사용할 DB 연결 관련 내용(JDBC, MYbais, DBCP), AOP, 트랜잭션 처리, 파일 업로드
등을 처리 -->
<!-- DBCP 사용을 위한 DataSource를 Bean으로 등록 -->
<!-- DataSource란? : java에서 Connection Pool을 지원하기 위한 인터페이스 -->
<!-- BasicDataSource : DataSource인터페이스를 구현한 클래스, 아파치 commons.dbcp에서 제공 -->
<!-- destroy-method="close" : 주어진 세션을 자동으로 반환(close)하라는 설정 -->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
<property name="username" value="project" />
<property name="password" value="project1234" />
<!-- defaultAutoCommit: SQL 수행 후 자동 COMMIT 설정. (기본값 : true) -->
<property name="defaultAutoCommit" value="false" />
<!-- 커넥션 풀 설정 -->
<property name="initialSize" value="10" /> <!-- 초기 커넥션 수, 기본 0 -->
<property name="maxTotal" value="500" /> <!-- 최대 커넥션 수, 기본 8 -->
<property name="maxIdle" value="100" /> <!-- 유휴 상태로 존재할 수 있는 커넥션 최대 수, 기본 8 -->
<property name="minIdle" value="10" /> <!-- 유휴 상태로 존재할 수 있는 커넥션 최소 수, 기본 0 -->
<property name="maxWaitMillis" value="-1" /> <!-- 예외 발생 전 커넥션이 반환 될 떄 까지 대기하는 최대 시간(ms), 기본 -1(무기한) -->
</bean>
</beans>
➰ mapper.xml 설정 / xml 작성 내용
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="memberMapper">
<!-- namespace : 공간(영역, 지역, 태그)의 이름-->
<!-- mapper 파일 생성 시 아래 태그 반드시 삭제 ! -->
<!-- <cache-ref namespace=""/> -->
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="memberMapper">
<!-- namespace : 공간(영역, 지역, 태그)의 이름 -->
<!-- mapper 파일 생성 시 아래 태그 반드시 삭제!!!!!!!! -->
<!-- <cache-ref namespace=""/> -->
<!--
resultMap
- SELECT 조회 결과(ResultSet) 컬럼명과
컬럼 값을 옮겨 담을 DTO의 필드명이 같지 않을 때
이를 매핑 시켜 SELECT시 자동으로 담기게 하는 역할
- 속성
type : 연결할 DTO (패키지명 + 클래스명 또는 별칭)
id : 만들어진 resultMap을 지칭할 식별명(이름)
<id> 태그 : PK 역할 컬럼 - 필드 매핑
<result> 태그 : <id>제외 나머지
-->
<resultMap type="Member" id="member_rm">
<!-- DB의 기본 키(복합키면 여러 개 작성) -->
<id property="memberNo" column="MEMBER_NO" />
<!-- DB의 일반 컬럼들 -->
<result property="memberEmail" column="MEMBER_EMAIL" />
<result property="memberPw" column="MEMBER_PW" />
<result property="memberNickname" column="MEMBER_NICKNAME" />
<result property="memberTel" column="MEMBER_TEL" />
<result property="memberAddress" column="MEMBER_ADDR" />
<result property="profileImage" column="PROFILE_IMG" />
<result property="enrollDate" column="ENROLL_DATE" />
<result property="memberDeleteFlag" column="MEMBER_DEL_FL" />
<result property="authority" column="AUTHORITY" />
</resultMap>
<!--
SQL 관련 태그 속성
- parameterType : 전달 받은 값의 자료형
기본 : 패키지명 + 클래스명
별칭 : Mybatis 별칭 또는 사용자 지정 별칭
- parameterMap : (사용 안함)
- resultType : select 결과를 담아서 반환할 자료형
단, DTO를 작성할 경우 필드명 = 컬럼명 인 경우만 가능
memberNo MEMBER_NO
- resultMap : select 결과의 컬럼명과
결과를 저장할 DTO 필드명이 다를 경우
이를 알맞게 매핑(연결)시켜주는 <resultMap> id 작성
-->
<!--
** 마이바티스에서 전달 받은 값을 SQL에 작성하는 방법 **
#{변수명|필드명} : PreparedStatement
: SQL에 값 대입 시 양쪽에 '' 붙여서 대입
${변수명|필드명} : Statement
: SQL에 값 대입 시 양쪽에 아무것도 붙이지 않음
사용 예시)
test1 = "user01"
test2 = MEMBER_EMAIL
- MEMBER_EMAIL이 'user01'인 회원 조회
SELECT * FROM MEMBER WHERE ${test2} = #{test1}
MEMBER_EMAIL = 'user01'
-->
<!-- parameterType="Member"은 mybatis-config에서 별칭 지정해줌 -->
<select id="login" parameterType="Member" resultMap="member_rm">
SELECT MEMBER_NO, MEMBER_EMAIL, MEMBER_NICKNAME,
MEMBER_TEL, MEMBER_ADDR, PROFILE_IMG, AUTHORITY,
TO_CHAR(ENROLL_DATE, 'YYYY"년" MM"월" DD"일" HH24"시" MI"분" SS"초"') AS ENROLL_DATE
FROM "MEMBER"
WHERE MEMBER_DEL_FL = 'N'
AND MEMBER_EMAIL = #{memberEmail}
AND MEMBER_PW = #{memberPw}
</select>
</mapper>
➰ 암호화에 필요한 내용 등록
porm.xml에 내용 추가
<!-- Spring-security -->
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-core -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.7.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.7.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.7.1</version>
</dependency>
web.xml에 내용 추가
<!-- The definition of the Root Spring Container shared by all Servlets
and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring/root-context.xml
🌝 classpath:spring/spring-security.xml
</param-value>
</context-param>
spring file 만들기 (아래 위치와 내용에 맞게 생성하기)
Namespaces 클릭해서 아래 내용 체크
✳ spring-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-5.7.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- xml을 이용한 bcrypt 암호화 객체를 bean으로 등록 -->
<bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
</beans>
✳ ExceptionController.java
package edu.kh.project.common;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
// 예외 처리용 컨트롤러 (프로젝트 전역)
@ControllerAdvice
public class ExceptionController {
@ExceptionHandler(Exception.class)
public String exceptionHandler(Exception e, Model model) {
// Exception e : 예외 정보를 담고 있는 객체
// Model model : 데이터 전달용 객체 (request scope가 기본)
e.printStackTrace(); // 예외 내용/발생 메소드 확인
model.addAttribute("e", e);
// forward 진행
// -> View Resolver의 prefix, suffix를 붙여 JSP 경로로 만듦
return "common/error";
}
}
🤔💭 새로운 지식
@SessionAttributes("loginMember")
: Model의 이름(key)를 적으면 session으로 추가
(여러개라면 배열형태로 작성 {"loginMember","test","pw"}
Model
: 데이터 전달 용 객체
: 데이터를 K : V 형식으로 담아서 전달
: request scope @sessiobAttributes 어노테이션 함께 사용 시 Session scope
RedirectAttributes
: 리다이렉트 시 데이터를 request scope로 전달 할 수 있게 하는 객체
SessionStatus status
: 세션 상태를 관리하는 객체
( status.setComplete(); -> 세션 무효화)
728x90
'ON > spring' 카테고리의 다른 글
[Spring] 드롭다운 메뉴 | 회원정보 수정 ③ (0) | 2023.08.14 |
---|---|
[Spring] 회원가입 | 주소 API 활용 ② (0) | 2023.08.11 |
[Spring] Spring MVC 이란 ? (0) | 2023.08.11 |
[Spring] 설치 진행하기 (0) | 2023.08.10 |
[Spring] Framework | Library | Spring Framework 이란? (0) | 2023.08.10 |