티스토리 뷰

<작성기준: 이전 게시글[2]의 내용에서 아래 내용 추가>

<views, resources 다운로드: https://dev-junyeong.tistory.com/18>

스프링레거시 + Mysql < 마이바티스사용 >


<만들어야 하는 것>

1. RememberMeInterceptor

2. servlet-context

3. MemberController(쿠키내용 추가)

4. BoardController

5. BoardVO

6. BoardMapper.java

7. BoardMapper.xml

8. boardList.jsp

 


<주요사항>

1. RememberMeInterceptor 에서는 HandlerInterceptor인터페이스를 상속받는다. preHandle, postHandle, afterCompletion에 원하는 기능을 넣으면 된다. 

preHandle postHandle afterCompletion
컨트롤러 메소드 호출 이전에 실행 컨트롤러 메소드 호출 이후에 실행 컨트롤러, 뷰 실행완류이후 실행

2. servlet-context에 RememberMeInterceptor가 있는 패키지를 등록해줘야한다.

 

3. 게시판 리스트 관련해서 BoardVO, BoardController, BoardService, BoardMapper를 작성한다.

 

4. Mysql은 설정  [Edit] - [Preferences] - Sql Editor에서 safe모드 체크 해제해야 delete가 된다.

 

[MemberController]

package com.example.controller;

import java.util.Date;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.domain.MemberVO;
import com.example.service.MemberService;
import com.example.util.Script;

@Controller
@RequestMapping("/member/*")
public class MemberController {
	
	//스프링 빈들끼리는 memberMapper필요하네? 스프링이 주입시켜줌
	@Autowired
	private MemberService memberService;
	
	 
	@GetMapping("/join")
	public String join() {
		System.out.println("join 호출 됨...");
		return "member/join";
	}
	
	//ResponseEntity 응답데이터 html문서를 문자열로 간단하게 준다
	@PostMapping("/join")
	public ResponseEntity<String> join(MemberVO memberVO) {
		
		//비밀번호 암호화
		String passwd = memberVO.getPasswd();
		String hasedPw= BCrypt.hashpw(passwd, BCrypt.gensalt());
		memberVO.setPasswd(hasedPw);
		
		String birthday = memberVO.getBirthday();//하이픈 삭제 "2021-08-25"
		birthday = birthday.replace("-", "");//20210825
		memberVO.setBirthday(birthday);
		
		memberVO.setRegDate(new Date());//현재시점의 날짜 객체
		
		memberService.register(memberVO);
		System.out.println(memberVO);//이건 스프링세상이기때문에 프린트됨. 롬복??
//		String test = memberVO.toString();
//		System.out.println(test);
//		return "redirect:/member/login"; //새로고침하면 웹에 담겨있던 Post된 정보가 한번더 보내져서 에러
//		스프링방식으로 해보기
		HttpHeaders headers = new HttpHeaders();
		headers.add("Content-Type", "text/html; charset=UTF-8");//어떤 자료형인지 content-type
		String str = Script.href("회원가입 성공!", "/member/login");//자바스크립트 실행하는 방식
		return new ResponseEntity<String>(str, headers, HttpStatus.OK);
	}
	
	@GetMapping("/login")
	public String login() {
		return "member/login";
	}
	
	@PostMapping("/login")
	public ResponseEntity<String> login(String id, String passwd, String rememberMe, 
			HttpSession session, HttpServletResponse response) {
		
		MemberVO memberVO = memberService.getMemberById(id);
		
		boolean isPasswdSame = false;
		String message = "";
		if(memberVO != null) {
			isPasswdSame = BCrypt.checkpw(passwd, memberVO.getPasswd());
			if(isPasswdSame == false) {//비밀번호가 일치하지 않음
				message = "비밀번호가 일치하지 않습니다.";
			}
		} else {//memberVO == null // 일치하는 아이디가 없음
			message = "존재하지 않는 아이디 입니다.";
		}
		// 로그인 실패시 (없는 아이디이거나 비밀번호 틀렸을 때)
		if(memberVO == null || isPasswdSame == false) {
			HttpHeaders headers = new HttpHeaders();
			headers.add("Content-Type", "text/html; charset=UTF-8");
			String str = Script.back(message);
			
			return new ResponseEntity<String> (str,headers,HttpStatus.OK);//200번
		}
		//로그인 성공시, 로그인 인증하기
		session.setAttribute("id", id);//map인데 키값은 스트링만 쓸 수 있다.
		
		if(rememberMe != null) {
			Cookie cookie = new Cookie("id", id);
			cookie.setPath("/");
			cookie.setMaxAge(60*10);
			System.out.println("rememberMe작동중" + id);
			
			response.addCookie(cookie);
		}
		
		HttpHeaders headers = new HttpHeaders();
		headers.add("Location", "/");//redirect 홈으로 보내는 경로
		//
		return new ResponseEntity<String>(headers, HttpStatus.FOUND);//302번
	}//login
	/*
	 * 영역객체 4가지 application : 웹프로그램 한개당 유지됨 session : 사용자 한명당 유지됨 request : 사용자 요청
	 * 한개당 유지됨 pageContext : JSP 화면 한개 처리할동안 유지됨
	 * 
	 * 영역(scope)객체 수명주기 application > session > request > pageContext
	 * 
	 * el언어에서 검색순서 ${ id } pageScope -> requestScope -> sessionScope ->
	 * applicationScope
	 * 그래서 결론: jsp에서 sessionScope.id 안해도 id를 불러올 수 있는 것이다.
	 */
	
	@GetMapping("/logout")
	public String logout(HttpSession session, HttpServletRequest request, HttpServletResponse response) {
		session.invalidate();
		
		//로그인 상태유지용 쿠키 있으면 삭제하기
		Cookie[] cookies = request.getCookies();
		
		if(cookies != null) {
			for(Cookie cookie : cookies) {
				if(cookie.getName().equals("id")) {
					cookie.setMaxAge(0);//브라우저가 삭제할 수 있도록 0으로 설정
					cookie.setPath("/");
					
					response.addCookie(cookie);
				}
			}//for
		}
		return "redirect:/";
	}
}

 

[servlet-context.xml]

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	<beans:bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver" />
	
	
	<context:component-scan base-package="com.example.controller" />
	
	
<!--   	<beans:bean id="loginCheckInterceptor" class="com.example.interceptor.LoginCheckInterceptor" />-->
	
	<interceptors>
		<interceptor>
			<mapping path="/**" />
			<beans:bean class="com.example.interceptor.RememberMeInterceptor" />
		</interceptor>
		
	</interceptors> 

</beans:beans>

 

[BoardVO]

package com.example.domain;

import java.util.Date;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class BoardVO {
	
	private int num;//글번호
	private String mid;
	private String subject;
	private String content;
	private int readcount;
	private Date regDate;
	private String ipaddr;
	private int reRef; //글 그룹 번호, 주글 번호와 같음
	private int reLev;//글목록에서 글 들여쓰기 레벨
	private int reSeq;//글 그룹 내에서의 순번
}

 

[BoardController]

package com.example.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/board/*")
public class BoardController {
	
	@GetMapping("/list")
	public String list() {
		System.out.println("list 호출...");
		
		return "board/boardList";
	}
}

 

[BoardMapper.java]

package com.example.mapper;

import com.example.domain.BoardVO;

public interface BoardMapper {
	int insert(BoardVO boardVO);
	
}

 

[BoardMapper.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="com.example.mapper.BoardMapper">
<!-- BoardMapper.java에서 메서드명을 id에 적고,  CDATA는 문자그대로 해석(연산자x)
DB에선 reg_date 스프링VO에선 regDate
오라클은 오토시퀀스, Mysql은 해당 컬럼에 오토인크리먼트
SELECT는 꼭 resultType을 더 적어줘야한다. 마이바티스 공식사이트 매퍼설정 typeAliases-->
  <insert id="selectBlog">
    <![CDATA[
    			INSERT INTO board (num, mid, subject, content, readcount, reg_date, ipaddr, re_ref, re_lev, re_seq)
		VALUES (#{num}, #{mid}, #{subject}, #{content}, #{readcount}, #{regDate}, #{ipaddr}, #{reRef}, #{reLev}, #{reSeq})
    ]]>
  </insert>
  
  <select id="nextNum" resultType="int">
  	<![CDATA[
  		SELECT IFNULL(MAX(num), 0) + 1 AS bnum FROM board
  	]]>
  </select>
  
</mapper>

'웹개발 > 스프링연습' 카테고리의 다른 글

[2]Spring-legacy [로그인, 로그아웃 추가]  (0) 2021.11.15
[1]Spring-legacy [회원가입]  (0) 2021.11.14