티스토리 뷰
<작성기준: 이전 게시글[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 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 자바를 코틀린으로
- 안드로이드스튜디오 프로젝트 자동해제
- 파이어베이스
- 로또
- 깃헙
- github
- 안드로이드
- 프로젝트 자동해제
- 안드로이드스튜디오 협업
- build.gradle
- mybatis
- Mapper
- 안드로이드 네비게이션
- 클라우드DB
- ConstraintLayout
- git
- json-server
- 마이바티스
- Kotlin
- 안드로이드스튜디오 github
- 안드로이드 프래그먼트컨테이너
- 코틀린
- 컨스트레인트
- cmd
- Realtime Database
- 프로젝트 자동
- 매퍼
- var
- Firebase
- 안드로이드 프래그먼트
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
글 보관함