mapper 파일 생성 시 반드시 해야되는 것!
1. cache-ref 태그 삭제
2. mapper 태그에 namespace 속성 추가
-> namespace : 해당 파일을 쉽게 부르는 이름(DAO에서 사용)
#{변수명} : SQL에 값이 포함될 때 양쪽에 '' 추가됨 (pstmt)
-> 리터럴 사용(값 자체로 사용)
${변수명} : SQL에 값이 포함될 때 양쪽에 '' 추가되지 않음(stmt)
-> SQL 구문 조합시 사용(condition)
수행하려는 SQL에 따라서 태그가 구분됨(사용 가능한 속성도 다름)
<select id=""></select>
<insert id=""></insert>
<update id=""></update>
<delete id=""></delete>
1) resultType : 조회 결과가 1행 1열인 경우에만 작성
조회된 데이터의 Java 자료형을 Mybatis 별칭 형태로 작성
[Mybatis 별칭]
java : _int
Integer : int
String : string(java.lang.String)
<select id="test1" resultType="_int">
SELECT COUNT(*) FROM MEMBER
</select>
[resultMap 속성]
1) type : 조회 결과를 담을 VO의 타입 또는 별칭
2) id : 만들어진 resultMap 태그를 지정할 이름(식별명)
[resultMap 내부 작성 태그]
<id> : PK 역할의 컬럼 - 필드 연결 <result> : PK을 제외한 나머지 컬럼 - 필드연결
<resultMap type="member" id="member_rm">
<id property="memberNo" column="MEMBER_NO"/>
<result property="memberEmail" column="MEMBER_EMAIL"/>
<result property="memberPw" column="MEMBER_PW"/>
<result property="memberNickname" column="MEMBER_NICK"/>
<result property="memberTel" column="MEMBER_TEL"/>
<result property="memberAddress" column="MEMBER_ADDR"/>
<result property="profileImage" column="PROFILE_IMG"/>
<result property="enrollDate" column="ENROLL_DT"/>
<result property="secessionFlag" column="SECESSION_FL"/>
</resultMap>
<!-- VO 클래스의 패키지명 + 클래스명 모두 작성하는것이 불편하기 때문에 짧은 별칭 부여 -->
<typeAliases>
<typeAlias type="edu.kh.comm.member.model.vo.Member" alias="member"/>
</typeAliases>
edu.kh.comm.member.model.vo.Member 부분 -> member 별칭을 만들어
parameterType="member"로 사용
--------------------------------------------------------------------------------
### memberController
// POJO 기반 프레임워크 : 외부 라이브러리 상속 X
// class : 객체를 만들기위한 설계도
// -> 객체로 생성 되어야지 기능 수행 가능하다.
// -> IOC(제어의 역전, 객체 생명주기를 스프링이 관리)를 이용하여 객체 생성
// 이 때, 스프링이 생성한 객체를 bean 이라고 한다.
// bean 등록 == 스프링이 객체로 만들어서 가지고 있어라
// @Component // 해당 클래스를 bean으로 등록하라고 프로그램에게 알려주는 주석(Annotation)
@Controller // 생성된 bean이 Controller임을 명시 + bean 등록
@RequestMapping("/member") // localhost:8080/comm/member 이하의 요청을 처리하는 컨트롤러
//localhost:8080/comm/member
//localhost:8080/comm/member/login
//localhost:8080/comm/member/signUp
@SessionAttributes({"loginMember"}) // Model에 추가된 값의 key와 어노테이션에 작성된 값이 같으면
// 해당 값을 session scope로 이동시키는 역할
public class MemberController {
private Logger logger = LoggerFactory.getLogger(MemberController.class);
// private MemberService service = new MemberServiceImpl(); IOC (제어의 역전) : new 연산자를 통해서 개발자가 직접 객체 생성하지 않는다.
@Autowired // bean으로 등록된 객체 중 타입이 같거나, 상속관계인 bean을 주입해주는 역할
private MemberService service; // -> DI(의존성 주입) / @Service가 선행되어야 함
// Controller : 요청/응답을 제어하는 역할을 하는 클래스
/* @RequestMapping : 클라이언트 요청(url)에 맞는 클래스 or 메서드를 연결 시켜주는 어노테이션
*
* [ 위치에 따른 해석 ]
* - 클래스 레벨 : 공통 주소
* - 메서드 레벨 : 공통 주소 외 나머지 주소
*
* 단, 클래스레벨에 @RequestMapping이 존재하지 않는다면
* - 메서드 레벨 : 단독 요청 처리주소
*
*
* [ 작성법에 따른 해석 ]
*
* 1) @RequestMapping("url")
* --> 요청방식(GET/POST) 관계 없이 url이 일치하는 요청 처리
*
* 2) @RequestMapping(value="url", method="RequestMethod.Get | POST")
* --> 요청 방식에 따라 요청 처리함
*
* ** 메서드 레벨에서 GET/POST 방식을 구분하여 매핑할 경우 **
* @GetMapping("url") / @PostMapping("url") 사용하는것이 일반적
* (메서드 레벨에서만 작성 가능!)
*
* */
// 로그인
// 요청 시 파라미터를 얻어오는 방법 1
// HttpServletRequest 이용
//localhost:8080/comm/login
// @RequestMapping("/login")
// public String login(HttpServletRequest req) {
// logger.info("로그인 요청됨");
//
// String inputEmail = req.getParameter("inputEmail");
// String inputPw = req.getParameter("inputPw");
//
// logger.debug("inputEmail : " + inputEmail);
// logger.debug("inputPw : " + inputPw);
//
// return "redirect:/"; // sendRedirect 안써도 된다. 이게 리다이렉트 구문임.
// }
// 요청 시 파라미터를 얻어오는 방법 2
// -> @RequestParam 어노테이션 사용
//@RequestParam("name속성값") 자료형 변수명
// -> 클라이언트 요청 시 같이 전달된 파라미터를 변수에 저장
// --> 어떤 파라미터를 변수에 저장할지는 "name속성값"을 이용해 지정
// 매개변수 지정 시 데이터 타입 파싱을 자유롭게 징행할 수 있음 ex) String -> int 로 변환
// [속성]
// value : input 태그의 name 속성값
// reqired : 입력된 name 속성값이 필수적으로 파라미터에 포함되어야 하는지 지정
// reqired=true / false (기본값 true)
// defaultValue : reqired가 false인 상태에서 파라미터가 존재하지 않을 경우의 값을 지정
// @RequestMapping("/login")
// public String login(@RequestParam("inputEmail") String inputEmail,
// @RequestParam("inputPw") String inputPw,
// @RequestParam(value="inputName", required = false, defaultValue="홍길동") String inputName) {
//
// logger.debug("email : " + inputEmail);
// logger.debug("Pw : " + inputPw);
// logger.debug("inputName : " + inputName);
//
// // email 숫자만 입력받는다고 가정
// // logger.debug(inputEmail + 100);
//
// return "redirect:/";
// }
// 요청 시 파라미터를 얻어오는 방법 3
// -> @ModelAttribute 어노테이션 사용
// @ModelAttribute VO타입 변수명
// -> 파라미터중 name 속성값이 VO의 필드와 일치하면
// 해당 VO 객체의 필드에 값을 세팅
// ** @ModelAttribute를 이용해서 객체에 값을 직접 담는 경우에 대한 주의 사항 **
// -- 반드시 필요한 내용
// - VO 기본생성자 @NoArgsConstructor
// - VO 필드에 대한 Setter @Setter, @NoArgsConstructor
@PostMapping("/login")
public String login(/* @ModelAttribute */ Member inputMember,
Model model,
RedirectAttributes ra,
HttpServletResponse resp,
HttpServletRequest req,
@RequestParam(value="saveId", required=false) String saveId) {
// 커맨드 객체
// @ModelAttribute 생략된 상태에서 파라미터가 필드에 세팅된 객체
logger.info("로그인 기능 수행됨");
// 아이디, 비밀번호가 일치하는 회원 정보를 조회하는 Service 호출 후 결과 반환 받기
Member loginMember = service.login(inputMember);
/* Model : 데이터가 맵 형식(K:V) 형태로 담아 전달하는 용도의 객체
* -> request, session을 대체하는 객체
*
* - 기본 scope : request
* - session scope로 변환하고 싶은 경우
* 클래스 레벨로 @SessionAttributes를 작성하면 된다.
*
* @SessionAttributes 미작성 -> request scope
* */
if(loginMember != null) { // 로그인 성공 시
model.addAttribute("loginMember", loginMember); // == req.setAttribute("loginMember", loginMember);
// 로그인 성공 시 무조건 쿠키 생성
// 단, 아이디 저장 체크 여부에 따라서 쿠키의 유지시간을 조정
Cookie cookie = new Cookie("saveId", loginMember.getMemberEmail());
if(saveId != null) { // 아이디 저장 체크 되었을 때
cookie.setMaxAge(60 * 60* 24 * 365); // 초단위 지정(1년)
} else { // 체크되지 않았을 때
cookie.setMaxAge(0); // 0초 -> 생성되자마자 사라짐 == 쿠키삭제
}
// 쿠키가 적용될 범위(경로) 지정
cookie.setPath(req.getContextPath());
// 쿠키를 응답 시 클라이언트에게 전달
resp.addCookie(cookie);
} else {
// model.addAttribute("message", "아이디 또는 비밀번호가 일치하지 않습니다.");
ra.addFlashAttribute("message", "아이디 또는 비밀번호가 일치하지 않습니다.");
// redirect 시에도 request scope로 세팅된 데이터가 유지될 수 있도록 하는 방법을
// Spring에서 제공해줌
// -> RedirectAttributes 객체(컨트롤러 매개변수에 작성하면 사용 가능)
}
return "redirect:/";
}
// 로그아웃
@GetMapping("/logout")
public String logout(SessionStatus status) {
// 로그아웃 == 세션 없애는 것
// * @SessionAttributes을 이용해서 session scope에 배치된 데이터는
// SessionStatus라는 별토 객체를 이용해야만 없앨 수 있다.
logger.info("로그아웃 수행됨");
// session.invalidate(); 기존 세션 무효화 방식으로는 X
status.setComplete(); // 세션이 할일이 완료됨 -> 없앰
return "redirect:/"; // 메인페이지 재요청
}
// 회원가입 화면 전환
@GetMapping("/signUp") // Get 방식 : /comm/member/signUp 요청
public String signUp() {
return "member/signUp";
}
}