팀프로젝트 1일차

 

로그인 구현

1. DB 테이블 설계 ( Mysql 사용 )

member 테이블 ( CRUD )

CREATE TABLE `member` (
  `mno` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  `phone` varchar(20) DEFAULT NULL,
  `hiredate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `job` varchar(50) DEFAULT NULL,
  `deptno` int DEFAULT NULL,
  PRIMARY KEY (`mno`)
) ENGINE=InnoDB AUTO_INCREMENT=1019 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

 

 

dept ( 부서정보 저장용 ) 

CREATE TABLE `department` (
  `deptno` int NOT NULL,
  `dname` varchar(255) NOT NULL,
  `loc` varchar(255) NOT NULL,
  PRIMARY KEY (`deptno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

 

 

2. STS 4 ( 스프링부트 프로젝트 ) 설정

 

build.gradle

plugins {
	id 'java'
	id 'war'
	id 'org.springframework.boot' version '2.7.15'
	id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'com.study'
version = '0.0.1-SNAPSHOT'

java {
	sourceCompatibility = '11'
}

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	runtimeOnly 'com.mysql:mysql-connector-j'
	annotationProcessor 'org.projectlombok:lombok'
	providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	implementation 'javax.servlet:jstl'
    implementation "org.apache.tomcat.embed:tomcat-embed-jasper"
	implementation "org.springframework.boot:spring-boot-starter-jdbc"

	implementation('org.slf4j:jcl-over-slf4j')
	implementation('ch.qos.logback:logback-classic')
	implementation 'org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4:1.16'
	implementation 'org.springframework.boot:spring-boot-starter-validation'
}

tasks.named('test') {
	useJUnitPlatform()
}

 

application.properties

 

server.port=9092

spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp

•
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.datasource.url=jdbc:mysql://localhost:3306/spring5fs?serverTimezone=UTC&characterEncoding=UTF-8

spring.datasource.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.datasource.url=jdbc:log4jdbc:mysql://localhost:3306/33team?serverTimezone=UTC&characterEncoding=UTF-8


spring.datasource.username=33team
spring.datasource.password=33team

spring.messages.basename=message
spring.messages.encoding=UTF-8

 

3. DTO, DAO, 커맨드클래스, 서비스, 익셉션파일

 

DTO

package com.study.springboot.spring;

import java.time.LocalDateTime;

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

@AllArgsConstructor
@Getter
@NoArgsConstructor
@Setter
public class Member {

	private Long mno;
	private String name;
	private String password;
	private String phone;
	private LocalDateTime hiredate;
	private String job;
	private Integer deptno;

	public Member(long mno,String name ,String password, 
			String phone, LocalDateTime hiredate, String job, int deptno) {
		this.mno = mno;
		this.name= name;
		this.password = password;
		this.phone = phone;
		this.hiredate = LocalDateTime.now();
		this.job = job;
		this.deptno = deptno;
		
	}

	void setMno(Long mno) {
		this.mno = mno;
	}



	public void changePassword(String oldPassword, String newPassword) {
		if (!password.equals(oldPassword))
			throw new WrongIdPasswordException();
		this.password = newPassword;
	}

	public boolean matchPassword(String password) {
		return this.password.equals(password);
	}
}

 

DAO

package com.study.springboot.spring;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;

import lombok.RequiredArgsConstructor;


@Repository
public class MemberDao {


	@Autowired
	private JdbcTemplate jdbcTemplate;


	public Member selectByMno(Long Mno) {
		List<Member> results = jdbcTemplate.query(
				"select * from MEMBER where mno = ?",
				new RowMapper<Member>() {
					@Override
					public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
						Member member = new Member(
								rs.getLong("mno"), 
								rs.getString("NAME"),
								rs.getString("PASSWORD"),
								rs.getString("PHONE"), 
								rs.getTimestamp("hiredate").toLocalDateTime(), 
								rs.getString("job"), rs.getInt("deptno"));
						member.setMno(rs.getLong("mno"));
						return member;
					}
				}, Mno);

		return results.isEmpty() ? null : results.get(0);
	}
}

 

커맨드 클래스

package com.study.springboot.spring;

import java.time.LocalDateTime;

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

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class MemberInfo {

	private Long mno;
	private String name;
	private String phone;
	private String job;
	private Integer deptno;





}

 

서비스

package com.study.springboot.spring;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MemberService {

	@Autowired
	private MemberDao memberDao;


	public MemberInfo authenticate(Long mno, String password) {
		Member member = memberDao.selectByMno(mno);
		if (member == null) {
			throw new WrongIdPasswordException();
		}
		if (!member.matchPassword(password)) {
			throw new WrongIdPasswordException();
		}
		return new MemberInfo(member.getMno(),

				member.getName(), member.getPhone(), member.getJob(), member.getDeptno());
	}

}

 

익셉션

package com.study.springboot.spring;

public class WrongIdPasswordException extends RuntimeException {

}

 

메세지 파일

member.register=회원가입

term=약관
term.agree=약관동의
next.btn=다음단계

member.info=회원정보
mno=사번e
name=이름
password=비밀번호
password.confirm=비밀번호 확인
register.btn=가입 완료

register.done=<strong>{0}님 ({1})</strong>, 회원 가입을 완료했습니다.

go.main=메인으로 이동

required=필수항목입니다.
bad.mno=사번이 올바르지 않습니다.
duplicate.mno=중복된 사번 입니다.
nomatch.confirmPassword=비밀번호와 확인이 일치하지 않습니다.

login.title=로그인
login.btn=로그인하기
idPasswordNotMatching=아이디와 비밀번호가 일치하지 않습니다.
login.done=로그인에 성공했습니다.
remembermno=사번 기억하기

change.pwd.title=비밀번호 변경
currentPassword=현재 비밀번호
newPassword=새 비밀번호
change.btn=변경하기
notMatching.currentPassword=비밀번호를 잘못 입력했습니다.
change.pwd.done=비밀번호를 변경했습니다.

 

 

4. 컨트롤러, 커맨드

 

로그인 컨트롤러

package com.study.springboot.controller;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.study.springboot.spring.MemberInfo;
import com.study.springboot.spring.MemberService;
import com.study.springboot.spring.WrongIdPasswordException;

import lombok.extern.slf4j.Slf4j;


@Controller
@RequestMapping("/login")
@Slf4j 
public class LoginController {
	
	@Autowired
    private MemberService authService;


	@GetMapping
	public String form(LoginCommand loginCommand) {
		return "login/loginForm";
	}
	
	@PostMapping
	public String submit(LoginCommand loginCommand, Errors errors, HttpSession session) {
		new LoginCommandValidator().validate(loginCommand, errors);
		
		if(errors.hasErrors()) {
			return "login/loginForm";
		}
		try {
			MemberInfo memberInfo = authService.authenticate(loginCommand.getMno(),
															loginCommand.getPassword());
			
			// 로그인 session 테스트
			session.setAttribute("memberInfo", memberInfo);
			session.setAttribute("test", memberInfo);
			MemberInfo memberinfo = (MemberInfo) session.getAttribute("memberInfo");
			log.info("-----login------->" + memberInfo);
			
			
			
			return "login/loginSuccess";
		} catch (WrongIdPasswordException e) {
			errors.reject("idPasswordNotMatching");
			return "login/loginForm";
		}
	}
	
	

}

 

로그아웃 컨트롤러

package com.study.springboot.controller;

import javax.servlet.http.HttpSession;

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

@Controller
public class LogoutController {

	@RequestMapping("/logout")
	public String logout(HttpSession session) {
		session.invalidate();
		return "redirect:/main";
	}

}

 

커맨드 파일 ( jsp에서 입력받은거 처리 ) 

package com.study.springboot.controller;

public class LoginCommand {

	private Long mno;
	private String password;
	private boolean rememberMno;

	public Long getMno() {
		return mno;
	}

	public void setMno(Long mno) {
		this.mno = mno;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public boolean isRememberMno() {
		return rememberMno;
	}

	public void setRememberMno(boolean rememberMno) {
		this.rememberMno = rememberMno;
	}

}

 

 

JSP ( 실행 )

 

loginForm.jsp

<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html>
<html>
<head>
    <title><spring:message code="login.title" /></title>
</head>
<body>
    <form:form modelAttribute="loginCommand">
    <form:errors />
    <p>
        <label><spring:message code="mno" />:<br>
        <form:input path="mno" />
        <form:errors path="mno"/>
        </label>
    </p>
    <p>
        <label><spring:message code="password" />:<br>
        <form:password path="password" />
        <form:errors path="password"/>
        </label>
    </p>

    <input type="submit" value="<spring:message code="login.btn" />">
    </form:form>
</body>
</html>

 

 

loginSuccess.jsp

<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html>
<html>
<head>
    <title><spring:message code="login.title" /></title>
</head>
<body>
    <p>
        <spring:message code="login.done" />
    </p>
    <p>
        <a href="<c:url value='/main'/>">
            [<spring:message code="go.main" />]
        </a>
    </p>
</body>
</html>

 

main.jsp

<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
    <title>메인</title>
</head>
<body>
    <c:if test="${empty memberInfo}">
    <p>환영합니다.</p>
    <p>
        <a href="<c:url value="/join" />">[회원 가입하기]</a>
        <a href="<c:url value="/login" />">[로그인]</a>
    </p>
    </c:if>
    
    <c:if test="${! empty memberInfo}">
    <p>${memberInfo.name}님, 환영합니다.</p>
    <p>
        <a href="<c:url value="/edit/changePassword" />">[비밀번호 변경]</a>
        <a href="<c:url value="/logout" />">[로그아웃]</a>
    </p>
    </c:if>
</body>
</html>

 

 

 

'프로젝트 기반 자바(JAVA) 응용 SW개발자 취업과정' 카테고리의 다른 글

2023-09-06 77일차  (0) 2023.09.06
2023-09-05 76일차  (0) 2023.09.05
2023-09-01 74일차  (0) 2023.09.01
2023-08-31 73일차  (0) 2023.08.31
2023-08-30 72일차  (0) 2023.08.30

Spring Boot_STS4 프로젝트 복사 시 변경 될 곳 

 

1. 변경 필요한 파일

 

 

2. .project 파일 메모장 실행 <name> 부분 바꿀 프로젝트명 변경 

 

3. settings 파일 메모장으로 실행 후 바꿀 프로젝트명 변경

 

 

4. main파일에  Application빼고 앞 부분 바꾼 프로젝트명으로 변경

'프로젝트 기반 자바(JAVA) 응용 SW개발자 취업과정' 카테고리의 다른 글

2023-09-05 76일차  (0) 2023.09.05
2023-09-04 75일차  (0) 2023.09.04
2023-08-31 73일차  (0) 2023.08.31
2023-08-30 72일차  (0) 2023.08.30
2023-08-29 71일차  (0) 2023.08.30

스프링 부트 sts4_ 설치

 

1. 해당 사이트에서 설치 ( sts 4부터는 스프링부트에 특화 ) 3은 스프링 

 

 

2. jar파일 압축 해제 ( 더블 클릭 ) 

 

 

3. 압축 풀면 해당 폴더 생성됨 실행

 

 

4. 프로젝트 생성 위치 지정

 

5. New Spring Starter Project ( 프로젝트 생성 )

 

6. 프로젝트 이름, 버전, 패키징 ( war, jar 선택 ), Type ( Gredle, maven 선택 ) Next

 

7. 사용할 부트 버전, 디팬더시 선택

 

8. help => install New SoftWare 검색 후 설치

 

 

 

9.Preferences UTF-8 설정 HTML, CSS, jsp

 

 

10. application.properties에 port 설정, JSP 설정

 

11. build.gradle 사용 할 디팬더시 설정

 

 

12. lombok 설정 ( jar파일 cmd 실행, 설치창에 sts적용되는지 확인 

 

'프로젝트 기반 자바(JAVA) 응용 SW개발자 취업과정' 카테고리의 다른 글

2023-09-04 75일차  (0) 2023.09.04
2023-09-01 74일차  (0) 2023.09.01
2023-08-30 72일차  (0) 2023.08.30
2023-08-29 71일차  (0) 2023.08.30
2023-08-25 69일차  (0) 2023.08.25

MVC 3 쿠키(이메일 기억하기)

 

컨트롤러에서 쿠키 사용하기

 

1. 커맨드 클래스 필요 ( rememberEmail )

package controller;

public class LoginCommand {

	private String email;
	private String password;
	private boolean rememberEmail;

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public boolean isRememberEmail() {
		return rememberEmail;
	}

	public void setRememberEmail(boolean rememberEmail) {
		this.rememberEmail = rememberEmail;
	}

}

 

2. loginForm.jsp 이메일 기억하기 선택 항목 추가

<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html>
<html>
<head>
    <title><spring:message code="login.title" /></title>
</head>
<body>
    <form:form modelAttribute="loginCommand">
    <form:errors />
    <p>
        <label><spring:message code="email" />:<br>
        <form:input path="email" />
        <form:errors path="email"/>
        </label>
    </p>
    <p>
        <label><spring:message code="password" />:<br>
        <form:password path="password" />
        <form:errors path="password"/>
        </label>
    </p>
    
    <p> <!-- 해당 코드 추가 -->
    	<label><spring:message code="rememberEmail" />
    	<form:checkbox path="rememberEmail" />
    	
    	</label>
    
    </p>

    <input type="submit" value="<spring:message code="login.btn" />">
    </form:form>
</body>
</html>

 

3. LoginController의 form()메서드에 쿠키가 존재할 경우 폼에 전달할 커맨드 객체의 email 프로퍼티를

    쿠키의 값으로 설정 ( @CookieValue를 이용해서 쿠키를 전달받도록 설정 )

    @GetMapping
    public String form(LoginCommand loginCommand,
    		@CookieValue(value = "REMEMBER", required = false) Cookie rCookie) { // 이 부분! LoginCommand loginCommand
    	//model.addAttribute("loginCommand", new LoginCommand());
    	if(rCookie != null) {
    		loginCommand.setEmail(rCookie.getValue());
    		loginCommand.setRememberEmail(true);
    	}
    	
    	
    	return "login/loginForm";
    }

 

 

4. LoginController의submit()메서드에 이메일 기억하기 옵션을 선택한 경우 로그인 성공 후에 이메일을 담      고 있는 쿠키를 생성

    @PostMapping
    public String submit(LoginCommand loginCommand, Errors errors
    		                                 , HttpSession session, HttpServletResponse response) {
        new LoginCommandValidator().validate(loginCommand, errors);
        if (errors.hasErrors()) {
            return "login/loginForm";
        }
        try {
            AuthInfo authInfo = authService.authenticate(
                    loginCommand.getEmail(),
                    loginCommand.getPassword());
            session.setAttribute("authInfo", authInfo);
            session.setAttribute("test", authInfo);
            //세션에 authinfo 저장해야 함.
            AuthInfo authInfo1 = (AuthInfo) session.getAttribute("authInfo");
            log.info("-------------------"+authInfo1);
            
            // 쿠키 생성
            Cookie rememberCookie = new Cookie("REMEMBER", loginCommand.getEmail());
            rememberCookie.setPath("/");
            if(loginCommand.isRememberEmail()) {
            	rememberCookie.setMaxAge(60 * 60 * 24 * 30); // 30일 쿠키 저장 기간
            }else {
				rememberCookie.setMaxAge(0);
			}
            response.addCookie(rememberCookie);
            	
            	
            return "login/loginSuccess";
        } catch (WrongIdPasswordException e) {
            errors.reject("idPasswordNotMatching");
            return "login/loginForm";
        }
    }

 

5. label.properties에 메시지를 추가

rememberEmail=이메일 기억하기

 

 

결과

 

 

 

MVC 4 : 날짜 값 변환_가입일 from~to 조회 기능

 

날짜를 이용한 회원 검색 기능

 

1. DAO에 selectByRegdate() 메서드 추가 

REGDATE 값이 두 파라미터로 전달받은 from과 to 사이에 있는 Member 목록을 구한다

	public class MemberDao {

	private JdbcTemplate jdbcTemplate;

	public MemberDao(DataSource dataSource) {
		this.jdbcTemplate = new JdbcTemplate(dataSource);
	}
    
    public List<Member> selectByRegdate(LocalDateTime from, LocalDateTime to){
		List<Member> result = jdbcTemplate.query("select * from MEMBER where REGDATE between ? and ? order by REGDATE desc",
				(rs, n) -> {
					Member member = new Member(
							rs.getString("EMAIL"),
							rs.getString("PASSWORD"),
							rs.getString("NAME"),
							rs.getTimestamp("REGDATE").toLocalDateTime());
					member.setId(rs.getLong("ID"));
					return member;
					
					
				}, from, to);
		return result;
	}
    }

 

 

2. 커맨드 객체 Date 타입 프로퍼티 변환처리 : @DateTimeFormat

커맨드 객체에 @DateTimeFormat 애노테이션이 적용되어 있으면 해당 애노테이션에서 지정한 형식을 이용해서 문자열을 LocalDateTime 타입으로 변환

package controller;

import java.time.LocalDateTime;

import org.springframework.format.annotation.DateTimeFormat;

import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ListCommand {
	@DateTimeFormat(pattern = "yyyyMMddHH") // 년 월 일 시간 
	private LocalDateTime from;
	
	@DateTimeFormat(pattern = "yyyyMMddHH")
	private LocalDateTime to;
	
	
	
	
}

 

 

3. 컨트롤러 생성

@RequestMapping으로 설정하면 GET, POST 둘 다 사용 가능 

package controller;

import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import spring.Member;
import spring.MemberDao;

@Controller
public class MemberListController {
	
	private MemberDao memberDao;
	
	public void setMemberDao(MemberDao memberDao) {
		this.memberDao = memberDao;
	}
	
	@RequestMapping("/members")
	public String list(@ModelAttribute("cmd") ListCommand listCommand, Errors errors ,Model model) {
		
		if(errors.hasErrors()) {
			return "member/memberList";
		}
		
		if(listCommand.getFrom() != null && listCommand.getTo() != null) {
			List<Member> members = memberDao.selectByRegdate(listCommand.getFrom(), listCommand.getTo());
			model.addAttribute("members", members);
		}
		return "member/memberList";
		
	}
	
}

 

 

4. ControllerConfig 설정 클래스에 관련 빈 설정 추가 

@Configuration
public class ControllerConfig {
	
	@Autowired
	private MemberDao memberDao;
    
    	@Bean
	public MemberListController memberListController() {
		MemberListController controller = new MemberListController();
		controller.setMemberDao(memberDao);
		return controller;
	}
    
    }

 

5. LocalDateTime 값을 원하는 형식으로 출력해주는 커스텀 태그 파일 작성

JSTL이 제공하는 날짜 형식 태그는 아쉽게도 자바 8의 LocalDateTime 타입은 지원하지 않는다.

태그파일을 사용해서 LocalDateTime 값을 지정한 형식으로 출력

<%@ tag body-content="empty" pageEncoding="utf-8" %>
<%@ tag import="java.time.format.DateTimeFormatter" %>
<%@ tag trimDirectiveWhitespaces="true" %>
<%@ attribute name="value" required="true" 
              type="java.time.temporal.TemporalAccessor" %>
<%@ attribute name="pattern" type="java.lang.String" %>
<%
	if (pattern == null) pattern = "yyyy-MM-dd";
%>
<%= DateTimeFormatter.ofPattern(pattern).format(value) %>

 

6. 입력과 출력할 수 있게 JSP 파일 생성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ taglib prefix="tf" tagdir="/WEB-INF/tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원조회</title>
</head>
<body>

	<form:form modelAttribute="cmd">
	
	<p>
	<label>from: <form:input path="from" /></label>
	<form:errors path="from" />
	~
	<label>to: <form:input path="to" /></label>
	<form:errors path="to" />
	<input type="submit" value="조회">
	</p>
	
	</form:form>
	
	<c:if test="${! empty members }">
	
	<table>
		<tr>
		<th>아이디</th><th>이메일</th>
		<th>이름</th><th>가입일</th>
		</tr>
	<c:forEach var="mem" items="${members }">
	
		<tr>
		<td>${mem.id }</td>
		<td><a href="<c:url value="/members/${mem.id }"/>">${mem.email }</a></td>
		<td>${mem.name }</td>
		<td><tf:formatDateTime value="${mem.registerDateTime }" pattern="yyyy-MM-dd" /></td>
		
		</tr>
		</c:forEach>
	</table>
	
	</c:if>
	
</body>
</html>

 

 

결과

'프로젝트 기반 자바(JAVA) 응용 SW개발자 취업과정' 카테고리의 다른 글

2023-09-01 74일차  (0) 2023.09.01
2023-08-31 73일차  (0) 2023.08.31
2023-08-29 71일차  (0) 2023.08.30
2023-08-25 69일차  (0) 2023.08.25
2023-08-24 68일차  (0) 2023.08.24

스프링 MVC 3 세션, 인터셉터, 필터

 

비밀번호 변경 기능 구현

DTO

 

ChangePassword 메소드

package spring;

import java.time.LocalDateTime;

public class Member {

	private Long id;
	private String email;
	private String password;
	private String name;
	private LocalDateTime registerDateTime;

	public Member(String email, String password, 
			String name, LocalDateTime regDateTime) {
		this.email = email;
		this.password = password;
		this.name = name;
		this.registerDateTime = regDateTime;
	}

	void setId(Long id) {
		this.id = id;
	}

	public Long getId() {
		return id;
	}

	public String getEmail() {
		return email;
	}

	public String getPassword() {
		return password;
	}

	public String getName() {
		return name;
	}

	public LocalDateTime getRegisterDateTime() {
		return registerDateTime;
	}

	public void changePassword(String oldPassword, String newPassword) {
		if (!password.equals(oldPassword))
			throw new WrongIdPasswordException();
		this.password = newPassword;
	}

	public boolean matchPassword(String password) {
		return this.password.equals(password);
	}

}

 

form에서 현재 비밀번호와 새 비밀번호를 받기  위한 커맨드 객체 

package controller;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class ChangePwdCommand {

	private String currentPassword;
	private String newPassword;

}

 

 

DAO (변경 할 email 정보 데이터베이스에서 가져옴 )

	public Member selectByEmail(String email) {
		List<Member> results = jdbcTemplate.query(
				"select * from MEMBER where EMAIL = ?",
				new RowMapper<Member>() {
					@Override
					public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
						Member member = new Member(
								rs.getString("EMAIL"),
								rs.getString("PASSWORD"),
								rs.getString("NAME"),
								rs.getTimestamp("REGDATE").toLocalDateTime());
						member.setId(rs.getLong("ID"));
						return member;
					}
				}, email);

		return results.isEmpty() ? null : results.get(0);
	}

 


Service

package spring;

import org.springframework.transaction.annotation.Transactional;

public class ChangePasswordService {

	private MemberDao memberDao;

	@Transactional
	public void changePassword(String email, String oldPwd, String newPwd) {
		Member member = memberDao.selectByEmail(email);
		if (member == null)
			throw new MemberNotFoundException();

		member.changePassword(oldPwd, newPwd);

		memberDao.update(member);
	}

	public void setMemberDao(MemberDao memberDao) {
		this.memberDao = memberDao;
	}

}

 

 

입력 받은 객체를 검증할 Validator 클래스 작성

package controller;

import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

public class ChangePwdCommandValidator implements Validator {

	@Override
	public boolean supports(Class<?> clazz) {
		return ChangePwdCommand.class.isAssignableFrom(clazz);
	}

	@Override
	public void validate(Object target, Errors errors) {
		ValidationUtils.rejectIfEmptyOrWhitespace(
				errors, "currentPassword", "required");
		ValidationUtils.rejectIfEmpty(errors, "newPassword", "required");
	}

}

 

 

비밀번호 변경 요청을 처리하는 컨트롤러 클래스

로그인한 사용자 정보는 HttpSession의 authInfo 속성을 사용

package controller;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import spring.AuthInfo;
import spring.ChangePasswordService;
import spring.WrongIdPasswordException;

@Controller
@RequestMapping("/edit/changePassword")
public class ChangePwdController {

	private ChangePasswordService changePasswordService;

	public void setChangePasswordService(
			ChangePasswordService changePasswordService) {
		this.changePasswordService = changePasswordService;
	}

	@GetMapping
	public String form(
			@ModelAttribute("command") ChangePwdCommand pwdCmd) {
		return "edit/changePwdForm";
	}

	@PostMapping
	public String submit(
			@ModelAttribute("command") ChangePwdCommand pwdCmd,
			Errors errors,
			HttpSession session) {
		new ChangePwdCommandValidator().validate(pwdCmd, errors);
		if (errors.hasErrors()) {
			return "edit/changePwdForm";
		}
		AuthInfo authInfo = (AuthInfo) session.getAttribute("authInfo");
		try {
			changePasswordService.changePassword(
					authInfo.getEmail(),
					pwdCmd.getCurrentPassword(),
					pwdCmd.getNewPassword());
			return "edit/changedPwd";
		} catch (WrongIdPasswordException e) {
			errors.rejectValue("currentPassword", "notMatching");
			return "edit/changePwdForm";
		}
	}
}

 

 

changePwdForm.jsp

<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html>
<html>
<head>
    <title><spring:message code="change.pwd.title" /></title>
</head>
<body>
    <form:form>
    <p>
        <label><spring:message code="currentPassword" />:<br>
        <form:input path="currentPassword" />
        <form:errors path="currentPassword"/>
        </label>
    </p>
    <p>
        <label><spring:message code="newPassword" />:<br>
        <form:password path="newPassword" />
        <form:errors path="newPassword"/>
        </label>
    </p>
    <input type="submit" value="<spring:message code="change.btn" />">
    </form:form>
</body>
</html>

 

changedPwd.jsp

<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html>
<html>
<head>
    <title><spring:message code="change.pwd.title" /></title>
</head>
<body>
    <p>
        <spring:message code="change.pwd.done" />
    </p>
    <p>
        <a href="<c:url value='/main'/>">
            [<spring:message code="go.main" />]
        </a>
    </p>
</body>
</html>

 

 

뷰 코드에서 사용 할 메시지 파일

change.pwd.title=비밀번호 변경
currentPassword=현재 비밀번호
newPassword=새 비밀번호
change.btn=변경하기
notMatching.currentPassword=비밀번호를 잘못 입력했습니다.
change.pwd.done=비밀번호를 변경했습니다.

 

@Bean 등록

 

ControllerConfig

package config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import controller.ChangePwdController;
import controller.LoginController;
import controller.LogoutController;
import controller.RegisterController;
import spring.AuthService;
import spring.ChangePasswordService;
import spring.MemberRegisterService;

@Configuration
public class ControllerConfig {

	
	@Autowired
	private ChangePasswordService changePasswordService;

	
	@Bean
	public ChangePwdController changePwdController() {
		ChangePwdController changePwdController = new ChangePwdController();
		changePwdController.setChangePasswordService(changePasswordService);
		return changePwdController;
	}

}

 

MemberConfig

package config;

import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import spring.AuthService;
import spring.ChangePasswordService;
import spring.MemberDao;
import spring.MemberRegisterService;

@Configuration
@EnableTransactionManagement
public class MemberConfig {

	@Bean(destroyMethod = "close")
	public DataSource dataSource() {
		DataSource ds = new DataSource();
		ds.setDriverClassName("com.mysql.jdbc.Driver");
		ds.setUrl("jdbc:mysql://localhost/spring5fs?characterEncoding=utf8");
		ds.setUsername("spring5");
		ds.setPassword("spring5");
		ds.setInitialSize(2);
		ds.setMaxActive(10);
		ds.setTestWhileIdle(true);
		ds.setMinEvictableIdleTimeMillis(60000 * 3);
		ds.setTimeBetweenEvictionRunsMillis(10 * 1000);
		return ds;
	}

	@Bean
	public PlatformTransactionManager transactionManager() {
		DataSourceTransactionManager tm = new DataSourceTransactionManager();
		tm.setDataSource(dataSource());
		return tm;
	}

	@Bean
	public MemberDao memberDao() {
		return new MemberDao(dataSource());
	}



	@Bean
	public ChangePasswordService changePwdSvc() {
		ChangePasswordService pwdSvc = new ChangePasswordService();
		pwdSvc.setMemberDao(memberDao());
		return pwdSvc;
	}
	

}

 

 

인터셉터 사용하기

로그인이 되지 않았는데 비밀번호 변경페이지로 들어가게 되면 로그인페이지로 이동되게 하기

 

컨트롤러에서 로그인 객체가 존재하는 검사하고 로그인이 안되있으면 login페이지로 리다이렉트 할 수도 있지만

많은 기능에 로그인 여부를 확인을 할 수도 있기 때문에 인터셉터를 사용해야 된다.

if(authInfo == null){
	return "redirect:/login";
}

 

HandlerInterceptor 구현

preHandel() 메서드는 HttpSession에 "authInfo" 속성이 존재하면 true를 리턴

존재하지 않으면 리다이렉트 응답을 생성한 뒤 false를 리턴

 

package interceptor;

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

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class AuthCheckInterceptor implements HandlerInterceptor {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		
		log.info("[{preHandle}]");
		
		HttpSession session = request.getSession(false);
		if(session != null) {
			Object authInfo = session.getAttribute("authInfo");
			if(authInfo != null) {
				return true;
			}
		}
		
		response.sendRedirect(request.getContextPath()+ "/login");
		return false;
		
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		log.info("[{postHandle}]");
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		log.info("[{afterCompletion}]");
	}
	
	
	
	
	
	
	
}

 

 

MvcConfig 설정 클래스에  addInterceptors()메서드 오버라이드 

메서드 오버라이드는 소스에서 직접 오버라이드 해줘야 된다.

addPathPatterns("/edit/**")
해당 경로는 디렉터리가 아니라 컨트롤러 경로 / 매핑 주소
@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
	
	
	
	
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		
		registry.addInterceptor(authCheckInterceptor()).addPathPatterns("/edit/**")
														.excludePathPatterns("/edit/help/**");
		
	}
	
	@Bean
	public AuthCheckInterceptor authCheckInterceptor() {
		return new AuthCheckInterceptor();
	}

 

 

 

 

필터(Filter)로 위에 기능 구현 해보기

 

1. 필터 구현 

package filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class LogFilter implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		log.info("-------------LogFilter.init");
		
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		log.info("-------------LogFilter.dofilter");
		chain.doFilter(request, response);// 해당 코드있어야 인터셉터로 넘어감
		
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

}

 

package filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.util.PatternMatchUtils;

import lombok.extern.slf4j.Slf4j;

@Slf4j
//@Order(Integer.MIN_VALUE)
public class LoginCheckFilter implements Filter {

    private static final String[] whitelist = {"/", "/order", "/login", "/logout", "/css/*"};

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String requestURI = httpRequest.getRequestURI();
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        try {
            log.info("인증 체크 필터 시작{}", requestURI);
            if (isLoginCheckPath(requestURI)) {
                log.info("인증 체크 로직 실행 {}", requestURI);
                HttpSession session = httpRequest.getSession(false);
                if (session == null || session.getAttribute("authInfo") == null) {
                    log.info("미인증 사용자 요청 {}", requestURI);
                    //로그인으로 리다이렉트
//                    httpResponse.sendRedirect(httpRequest.getContextPath() + "/login?redirectURL=" + requestURI);
//                    httpResponse.sendRedirect(httpRequest.getContextPath() + "/main");
                    RequestDispatcher dispatcher = request.getRequestDispatcher("/login");
                    dispatcher.forward(httpRequest, httpResponse);
                    return;
                }
            }
            chain.doFilter(request, response);

        } catch (Exception e) {
            throw e;
        } finally {
            log.info("인증 체크 필터 종료 {}", requestURI);
        }
    }

    /**
     * whiteList의 경우 인증 체크를 안하도록 한다.
     */
    private boolean isLoginCheckPath(String requestURI) {
        return !PatternMatchUtils.simpleMatch(whitelist, requestURI);
    }

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

}

 

2. web.xml 구현 한 filter 추가

	<filter>
		<filter-name>LogFilter</filter-name>
		<filter-class>filter.LogFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>LogFilter</filter-name>
		<url-pattern>/edit/*</url-pattern>
	</filter-mapping>
	
	<filter>
		<filter-name>LoginCheckFilter</filter-name>
		<filter-class>filter.LoginCheckFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>LoginCheckFilter</filter-name>
		<url-pattern>/edit/*</url-pattern>
	</filter-mapping>

'프로젝트 기반 자바(JAVA) 응용 SW개발자 취업과정' 카테고리의 다른 글

2023-08-31 73일차  (0) 2023.08.31
2023-08-30 72일차  (0) 2023.08.30
2023-08-25 69일차  (0) 2023.08.25
2023-08-24 68일차  (0) 2023.08.24
2023-08-23 67일차  (0) 2023.08.23

+ Recent posts