기존에 있던 테이블로 진행(userinfo 테이블)
/*
CREATE TABLE userinfo (
userid VARCHAR2(100) PRIMARY KEY,
password VARCHAR2(100),
name VARCHAR2(200),
email VARCHAR2(300),
auth NUMBER(1)
);
*/
/*
이름 널? 유형
-------- -------- -------------
USERID NOT NULL VARCHAR2(100)
PASSWORD VARCHAR2(100)
NAME VARCHAR2(200)
EMAIL VARCHAR2(300)
AUTH NUMBER(1)
*/
@Data
public class Userinfo {
private String userid;
private String password;
private String name;
private String email;
private int auth;
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.itwill09.mapper.UserinfoMapper">
<!-- UserinfoMapper 인터페이스와 매핑될 SQL 쿼리들 정의 -->
<!-- 회원정보 삽입 쿼리 -->
<insert id="insertUserinfo">
insert into userinfo values(#{userid}, #{password}, #{name}, #{email}, #{auth})
<!-- MyBatis가 파라미터로 전달받은 Userinfo 객체의 필드 값들을 테이블 컬럼에 삽입 -->
</insert>
<!-- 개인 회원정보를 조건에 맞게 업데이트하는 쿼리 -->
<update id="updateUserinfo">
update userinfo
<set>
<!-- 특정 필드의 값이 null이 아니고, 빈 문자열이 아닐 때만 해당 컬럼을 업데이트 -->
<if test="password != null and password != ''">
password=#{password},
<!-- 패스워드가 null이 아니고 빈 문자열이 아닐 경우 패스워드 업데이트 -->
</if>
<if test="name != null and name != ''">
name=#{name},
<!-- 이름이 null이 아니고 빈 문자열이 아닐 경우 이름 업데이트 -->
</if>
<if test="email != null and email != ''">
email=#{email},
<!-- 이메일이 null이 아니고 빈 문자열이 아닐 경우 이메일 업데이트 -->
</if>
<if test="auth == 1 or auth == 9">
auth=#{auth}
<!-- 권한(auth)이 1이거나 9일 경우에만 권한 값을 업데이트 -->
</if>
</set>
where userid=#{userid}
<!-- 특정 userid에 해당하는 행만 업데이트 -->
</update>
<!-- 회원정보 삭제 쿼리 -->
<delete id="deleteUserinfo">
delete from userinfo where userid=#{userid}
<!-- 주어진 userid 값을 가진 회원정보 삭제 -->
</delete>
<!-- 특정 회원정보를 검색하는 쿼리 (결과는 Userinfo DTO 객체로 반환) -->
<select id="selectUserinfo" resultType="Userinfo">
select userid, password, name, email, auth from userinfo where userid=#{userid}
<!-- 주어진 userid에 해당하는 회원정보를 검색 -->
</select>
<!-- 모든 회원정보를 검색하는 쿼리 (결과는 Userinfo DTO 객체 리스트로 반환) -->
<select id="selectUserinfoList" resultType="Userinfo">
select userid, password, name, email, auth from userinfo order by userid
<!-- 모든 회원정보를 검색하고 userid 기준으로 정렬 -->
</select>
</mapper>
import java.util.List;
import xyz.itwill09.dto.Userinfo;
public interface UserinfoMapper {
// 새로운 회원 정보를 userinfo 테이블에 삽입하는 메서드
// => 파라미터로 전달된 Userinfo 객체의 필드를 SQL 쿼리에 사용하여 삽입
// 반환값은 삽입된 행(row)의 개수
int insertUserinfo(Userinfo userinfo);
// 회원 정보를 수정하는 메서드
// => 전달된 Userinfo 객체의 userid를 기준으로 나머지 필드값을 업데이트
// 반환값은 수정된 행(row)의 개수
int updateUserinfo(Userinfo userinfo);
// 특정 userid에 해당하는 회원 정보를 삭제하는 메서드
// => 전달된 userid에 해당하는 회원 정보를 userinfo 테이블에서 삭제
// 반환값은 삭제된 행(row)의 개수
int deleteUserinfo(String userid);
// 특정 userid에 해당하는 회원 정보를 검색하는 메서드
// => 해당 userid에 맞는 Userinfo 객체를 반환
// 존재하지 않으면 null을 반환
Userinfo selectUserinfo(String userid);
// userinfo 테이블에 저장된 모든 회원 정보를 검색하는 메서드
// => 여러 회원 정보를 List<Userinfo> 형식으로 반환
List<Userinfo> selectUserinfoList();
}
import java.util.List;
import xyz.itwill09.dto.Userinfo;
public interface UserinfoDAO {
int insertUserinfo(Userinfo userinfo);
int updateUserinfo(Userinfo userinfo);
int deleteUserinfo(String userid);
Userinfo selectUserinfo(String userid);
List<Userinfo> selectUserinfoList();
}
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import lombok.RequiredArgsConstructor;
import xyz.itwill09.dto.Userinfo;
import xyz.itwill09.mapper.UserinfoMapper;
// @Repository: Spring에서 해당 클래스가 데이터 접근 객체(DAO)임을 명시하는 어노테이션
// => 해당 클래스를 Spring Bean으로 등록하고, 스프링 컨테이너에서 관리
@Repository
// @RequiredArgsConstructor: Lombok 어노테이션으로, final로 선언된 필드에 대해 생성자를 자동으로 생성
// => 여기서는 final 필드인 SqlSession 객체를 생성자 주입 방식으로 자동 주입받기 위함
@RequiredArgsConstructor
public class UserinfoDAOImpl implements UserinfoDAO {
// SqlSession: MyBatis에서 제공하는 객체로, 데이터베이스와의 상호작용(SQL 실행 등)을 수행
// => SqlSession 객체는 MyBatis 매퍼와 상호작용하며 SQL 쿼리를 실행하고, 결과를 반환
private final SqlSession sqlSession;
// 회원정보를 데이터베이스에 삽입하는 메서드
@Override
public int insertUserinfo(Userinfo userinfo) {
// getMapper: MyBatis가 제공하는 메서드로, UserinfoMapper 인터페이스의 구현체를 반환
// => 반환된 Mapper를 통해 insertUserinfo 메서드를 호출하여 SQL 쿼리 실행
return sqlSession.getMapper(UserinfoMapper.class).insertUserinfo(userinfo);
}
// 회원정보를 업데이트하는 메서드
@Override
public int updateUserinfo(Userinfo userinfo) {
// UserinfoMapper를 통해 updateUserinfo 메서드를 호출하여 SQL 쿼리 실행
return sqlSession.getMapper(UserinfoMapper.class).updateUserinfo(userinfo);
}
// 회원정보를 삭제하는 메서드
@Override
public int deleteUserinfo(String userid) {
// UserinfoMapper를 통해 deleteUserinfo 메서드를 호출하여 SQL 쿼리 실행
return sqlSession.getMapper(UserinfoMapper.class).deleteUserinfo(userid);
}
// 특정 회원정보를 조회하는 메서드
@Override
public Userinfo selectUserinfo(String userid) {
// UserinfoMapper를 통해 selectUserinfo 메서드를 호출하여 SQL 쿼리 실행 및 회원정보 반환
return sqlSession.getMapper(UserinfoMapper.class).selectUserinfo(userid);
}
// 모든 회원정보를 조회하는 메서드
@Override
public List<Userinfo> selectUserinfoList() {
// UserinfoMapper를 통해 selectUserinfoList 메서드를 호출하여 SQL 쿼리 실행 및 회원정보 리스트 반환
return sqlSession.getMapper(UserinfoMapper.class).selectUserinfoList();
}
}
public interface UserinfoService {
void addUserinfo(Userinfo userinfo);
void modifyUserinfo(Userinfo userinfo);
void removeUserinfo(String userid);
Userinfo getUserinfo(String userid);
List<Userinfo> getUserinfoList();
Userinfo loginAuth(Userinfo userinfo);
}
<!-- https://mvnrepository.com/artifact/org.mindrot/jbcrypt -->
<!-- => 암호화 처리 기능을 제공하기 위한 라이브러리 -->
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.4</version>
</dependency>
@Service
@RequiredArgsConstructor
public class UserinfoServiceImpl implements UserinfoService {
private final UserinfoDAO userinfoDAO;
@Transactional
@Override
public void addUserinfo(Userinfo userinfo) {
if(userinfoDAO.selectUserinfo(userinfo.getUserid()) != null) {
//예외를 명확히 구분하여 예외 처리시 사용하기 위해 예외클래스를 작성해 예외 발생
throw new ExistsUserinfoException("이미 사용중인 아이디를 입력 하였습니다.", userinfo);
}
//매개변수로 전달받은 회원정보의 비밀번호를 암호화 처리하여 필드값 변경
String hashedPassword=BCrypt.hashpw(userinfo.getPassword(), BCrypt.gensalt());
userinfo.setPassword(hashedPassword);
userinfoDAO.insertUserinfo(userinfo);
}
@Transactional
@Override
public void modifyUserinfo(Userinfo userinfo) {
if(userinfoDAO.selectUserinfo(userinfo.getUserid()) == null) {
throw new UserinfoNotFoundException();
}
if(userinfo.getPassword() != null && !userinfo.getPassword().equals("")) {
String hashedPassword=BCrypt.hashpw(userinfo.getPassword(), BCrypt.gensalt());
userinfo.setPassword(hashedPassword);
}
userinfoDAO.updateUserinfo(userinfo);
}
@Transactional
@Override
public void removeUserinfo(String userid) {
if(userinfoDAO.selectUserinfo(userid) == null) {
throw new UserinfoNotFoundException();
}
userinfoDAO.deleteUserinfo(userid);
}
@Override
public Userinfo getUserinfo(String userid) {
Userinfo userinfo=userinfoDAO.selectUserinfo(userid);
if(userinfo == null) {
throw new UserinfoNotFoundException();
}
return userinfo;
}
@Override
public List<Userinfo> getUserinfoList() {
return userinfoDAO.selectUserinfoList();
}
@Override
public Userinfo loginAuth(Userinfo userinfo) {
Userinfo authUserinfo=userinfoDAO.selectUserinfo(userinfo.getUserid());
if(authUserinfo == null) {//아이디 인증 실패
throw new LoginAuthFailException("아이디의 회원정보가 존재하지 않습니다.", userinfo.getUserid());
}
if(!BCrypt.checkpw(userinfo.getPassword(), authUserinfo.getPassword())) {//비밀번호 인증 실패
throw new LoginAuthFailException("아이디가 없거나 비밀번호가 맞지 않습니다.", userinfo.getUserid());
}
return authUserinfo;
}
}
회원정보를 등록할 때 사용자로부터 입력받은 회원정보의 아이디가 기존 회원정보의 아이디와 중복될 경우 발생되어 예외를 생성하기 위한 클래스
예외 처리에 필요한 값을 필드에 저장하여 사용
public class ExistsUserinfoException extends RuntimeException{
private static final long serialVersionUID = 1L;
// 예외 처리에 필요한 값을 저장하기 위한 필드 작성
// => 사용자로부터 입력받은 회원정보를 필드에
@Getter
private Userinfo userinfo;
public ExistsUserinfoException() {
}
public ExistsUserinfoException(String message, Userinfo userinfo) {
super(message);
this.userinfo = userinfo;
}
}
public class UserinfoNotFoundException extends RuntimeException{
public UserinfoNotFoundException() {
}
public UserinfoNotFoundException(String message) {
super(message);
}
}
public class LoginAuthFailException extends RuntimeException {
private static final long serialVersionUID = 1L;
@Getter
private String userid;
public LoginAuthFailException() {
// TODO Auto-generated constructor stub
}
public LoginAuthFailException(String message, String userid) {
super(message);
this.userid=userid;
}
}
public class BadRequestException extends RuntimeException{
private static final long serialVersionUID = 1L;
public BadRequestException() {}
public BadRequestException(String message) {
super(message);
}
}
@Controller
@RequestMapping("/userinfo")
@RequiredArgsConstructor
public class UserinfoController {
private final UserinfoService userinfoService;
//회원정보를 입력받기 위한 JSP 문서의 뷰이름을 반환하는 요청 처리 메소드
// => 관리자만 요청 가능한 페이지로 설정
@RequestMapping(value = "/write", method = RequestMethod.GET)
public String write(HttpSession session) {
Userinfo loginUserinfo=(Userinfo)session.getAttribute("loginUserinfo");
//페이지를 요청한 사용자가 비로그인 사용자이거나 관리자가 아닌 경우 인위적 예외 발생
if(loginUserinfo == null || loginUserinfo.getAuth() != 9) {
throw new BadRequestException("비정상적인 방법으로 페이지를 요청 하였습니다.");
}
return "userinfo/user_write";
}
@RequestMapping(value = "/write", method = RequestMethod.POST)
public String write(@ModelAttribute Userinfo userinfo, Model model) {
//매개변수로 전달받은 회원정보의 아이디가 중복될 경우 ExistsUserinfoException 발생
userinfoService.addUserinfo(userinfo);
return "redirect:/userinfo/login";
}
//인증정보를 입력받기 위한 JSP 문서의 뷰이름을 반환하는 요청 처리 메소드
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String login() {
return "userinfo/user_login";
}
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(@ModelAttribute Userinfo userinfo, Model model, HttpSession session) {
//매개변수로 전달받은 회원정보로 인증이 실패한 경우 LoginAuthFailException 발생
Userinfo authUserinfo=userinfoService.loginAuth(userinfo);
session.setAttribute("loginUserinfo", authUserinfo);
return "userinfo/user_login";
}
//로그아웃 처리하고 로그인 페이지를 요청할 수 있는 URL 주소를 반환하는 요청 처리 메소드
@RequestMapping("/logout")
public String logout(HttpSession session) {
//session.removeAttribute("loginUserinfo");
session.invalidate();
return "redirect:/userinfo/login";
}
@RequestMapping("/list")
public String list(Model model, HttpSession session) {
if(session.getAttribute("loginUserinfo") == null) {
throw new BadRequestException("비정상적인 방법으로 페이지를 요청 하였습니다.");
}
model.addAttribute("userinfoList", userinfoService.getUserinfoList());
return "userinfo/user_list";
}
//아이디를 전달받아 USERINFO 테이블에 저장된 행을 검색하여 Request Scope 속성값으로 저장하고
//회원정보를 출력하는 JSP 문서의 뷰이름을 반환하는 요청 처리 메소드
// => 로그인 사용자만 요청 가능한 페이지로 설정
@RequestMapping("/view")
public String view(@RequestParam String userid, Model model, HttpSession session) {
if(session.getAttribute("loginUserinfo") == null) {
throw new BadRequestException("비정상적인 방법으로 페이지를 요청 하였습니다.");
}
model.addAttribute("userinfo", userinfoService.getUserinfo(userid));
return "userinfo/user_view";
}
//아이디를 전달받아 USERINFO 테이블에 저장된 행을 검색하여 Request Scope 속성값으로 저장하고
//회원정보를 변경하는 JSP 문서의 뷰이름을 반환하는 요청 처리 메소드
// => 관리자만 요청 가능한 페이지로 설정
@RequestMapping(value = "/modify", method = RequestMethod.GET)
public String modify(@RequestParam String userid, Model model, HttpSession session) {
Userinfo loginUserinfo=(Userinfo)session.getAttribute("loginUserinfo");
//페이지를 요청한 사용자가 비로그인 사용자이거나 관리자가 아닌 경우 인위적 예외 발생
if(loginUserinfo == null || loginUserinfo.getAuth() != 9) {
throw new BadRequestException("비정상적인 방법으로 페이지를 요청 하였습니다.");
}
model.addAttribute("userinfo", userinfoService.getUserinfo(userid));
return "userinfo/user_modify";
}
//변경할 회원정보를 전달받아 USERINFO 테이블에 저장된 행을 변경하고 회원정보 출력 페이지를
//요청할 수 있는 URL 주소를 반환하는 요청 처리 메소드
@RequestMapping(value = "/modify", method = RequestMethod.POST)
public String modify(@ModelAttribute Userinfo userinfo, HttpSession session) {
userinfoService.modifyUserinfo(userinfo);
//로그인 사용자와 변경 처리된 사용자가 동일한 경우 세션에 저장된 권한 관련 속성값 변경
Userinfo loginUserinfo=(Userinfo)session.getAttribute("loginUserinfo");
if(loginUserinfo.getUserid().equals(userinfo.getUserid())) {
session.setAttribute("loginUserinfo", userinfoService.getUserinfo(userinfo.getUserid()));
}
return "redirect:/userinfo/view?userid="+userinfo.getUserid();
}
//아이디를 전달받아 USERINFO 테이블에 저장된 행을 삭제하고 회원목록 출력 페이지를 요청할
//수 있는 URL 주소를 반환하는 요청 처리 메소드
// => 관리자만 요청 가능한 페이지로 설정
@RequestMapping("/remove")
public String remove(@RequestParam String userid, HttpSession session) {
Userinfo loginUserinfo=(Userinfo)session.getAttribute("loginUserinfo");
//페이지를 요청한 사용자가 비로그인 사용자이거나 관리자가 아닌 경우 인위적 예외 발생
if(loginUserinfo == null || loginUserinfo.getAuth() != 9) {
throw new BadRequestException("비정상적인 방법으로 페이지를 요청 하였습니다.");
}
userinfoService.removeUserinfo(userid);
//로그인 사용자와 삭제 처리된 회원정보의 아이디가 동일한 경우 로그아웃 페이지로
//리다이렉트 이동 처리
if(loginUserinfo.getUserid().equals(userid)) {
return "redirect:/userinfo/logout";
}
return "redirect:/userinfo/list";
}
WEB-INF/views/userinfo 폴더
→ user_write.jsp
→ user_login.jsp
→ user_error.jsp
→ user_list.jsp
→ user_view.jsp
→ user_modify.jsp
요청 처리 메소드의 명령 실행 전 또는 실행 후에 실행될 명령을 제공하는 기능
HandlerInterceptor 인터페이스를 상속받은 interceptor 클래스를 작성하여 Spring Bean Configuration File(servlet-context.xml)에 Spring Bean으로 등록하고 인터셉트로 사용되도록 환경설정
HandlerInterceptor 인터페이스의 기본 메소드(Default Mehod) 중 필요한 메소드만 오버라이드 선언하여 사용
필터는 Front Controller의 이전 위치에 존재하여 실행되고 인터셉터는 Front Controller의 다음 위치에 존재하여 실행되어야한다.
필터는 WAS 프로그램에 의해 실행되고 인터셉터는 Front Controller에 의해 관리되어야한다.
관리자 관련 권한 처리를 위해 작성된 Interceptor 클래스
요청 처리 메소드 호출 전에 비로그인 사용자 또는 관리자가 아닌 사용자가 페이지를 요청할 경우 인위적 예외 발생
public class AdminAuthInterceptor implements HandlerInterceptor {
//요청 처리 메소드가 호출되기 전에 실행될 명령을 작성하기 위한 메소드
// => false 반환 : 요청 처리 메소드 미호출, true : 요청 처리 메소드 호출
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HttpSession session=request.getSession();
Userinfo loginUserinfo=(Userinfo)session.getAttribute("loginUserinfo");
if(loginUserinfo == null || loginUserinfo.getAuth() != 9) {
//포워드 이동 및 리다이렉트 이동 가능
//response.sendError(HttpServletResponse.SC_BAD_REQUEST);
//return false;
throw new BadRequestException("비정상적인 방법으로 페이지를 요청 하였습니다.");
}
return true;
}
//요청 처리 메소드가 호출된 후에 실행될 명령을 작성하기 위한 메소드
// => 요청 처리 메소드의 반환값(ViewName)으로 뷰를 생성하기 전에 실행될 명령을 작성
// => ModelAndView 객체를 제공받아 ModelAndView 객체에 저장된 정보를 변경할 때 사용
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
//요청 처리 메소드가 호출된 후에 실행될 명령을 작성하기 위한 메소드
// => 요청 처리 메소드의 반환값(ViewName)으로 뷰를 생성한 후에 실행될 명령을 작성
// => 뷰 관련 정보를 변경할 때 사용
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
public class LoginAuthInterceptor implements HandlerInterceptor {
//요청 처리 메소드가 호출되기 전에 실행될 명령을 작성하기 위한 메소드
// => false 반환 : 요청 처리 메소드 미호출, true : 요청 처리 메소드 호출
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HttpSession session=request.getSession();
Userinfo loginUserinfo=(Userinfo)session.getAttribute("loginUserinfo");
if(loginUserinfo == null) {
throw new BadRequestException("비정상적인 방법으로 페이지를 요청 하였습니다.");
}
return true;
}
}
<beans:bean class="xyz.itwill09.util.AdminAuthInterceptor" id="adminAuthInterceptor"/>
<beans:bean class="xyz.itwill09.util.LoginAuthInterceptor" id="loginAuthInterceptor"/>
interceptors: interceptor 엘리먼트를 등록하기 위한 엘리먼트
interceptor: Front Controller로 Interceptor 객체의 메소드를 호출하기 위한 규칙을 제공하기 위한 엘리먼트
mapping: 인터셉터가 동작될 요청 페이지 경로를 제공하는 엘리먼트
ref: Froont Controller에 의해 사용될 Interceptor 객체를 제공하기 위한 엘리먼트
exclude-mapping: 인터셉터가 동작되지 않는 요청 페이지 경로를 제공하는 엘리먼트
<interceptors>
<interceptor>
<mapping path="/userinfo/write"/>
<mapping path="/userinfo/modify"/>
<mapping path="/userinfo/remove"/>
<beans:ref bean="adminAuthInterceptor"/>
</interceptor>
<interceptor>
<mapping path="/userinfo/*"/>
<exclude-mapping path="/userinfo/login"/>
<beans:ref bean="loginAuthInterceptor"/>
</interceptor>
</interceptors>
@ControllerAdvice: 에외 처리 메소드만 작성된 Controller 클래스를 Spring Bean으로 등록하기 위한 어노테이션
=> 모든 Controller 클래스의 요청 처리 메소드에서 발생된 예외를 제공받아 예외 처리 가능
@ExceptionHandler: 예외 처리 기능을 제공하는 메소드를 설정하기 위한 어노테이션
=> Controller 클래스의 요청 처리 메소드에서 예외가 발생될 경우 예외 처리를 위해 Front Controller가 자동으로 호출하는 메소드 - 예외 처리 메소드(Spring AOP 기능 사용)
예외 처리 메소드에 매개변수를 작성하면 예외 처리에 필요한 객체를 Front Controller로부터 제공받아 사용할 수 있으며 클라이언트에게 응답할 뷰의 뷰이름 반환 - 리다이렉트 이동 가능
value 속성: 예외 처리하기 위한 클래스의 Class 객체를 속성값으로 설정
=> value 속성외에 다른 속성이 없는 경우 속성값만 설정 가능
=> 생략 가능
@ControllerAdvice
public class ExceptionController {
@ExceptionHandler(value = BadRequestException.class)
public String badRequestException() {
return "userinfo/user_error";
}
@ExceptionHandler(ExistsUserinfoException.class)
public String existsUserinfoException(ExistsUserinfoException exception, Model model) {
model.addAttribute("message", exception.getMessage());
model.addAttribute("userinfo", exception.getUserinfo());
return "userinfo/user_write";
}
@ExceptionHandler(LoginAuthFailException.class)
public String loginAuthFailException(LoginAuthFailException exception, Model model) {
model.addAttribute("message", exception.getMessage());
model.addAttribute("userid", exception.getUserid());
return "userinfo/user_login";
}
@ExceptionHandler(UserinfoNotFoundException.class)
public String userinfoNotFoundException() {
return "userinfo/user_error";
}
// 모든 예외를 처리하는 클래스
/*
@ExceptionHandler(Exception.class)
public String exception() {
return "userinfo/user_error";
}
*/
}
@Controller
@RequestMapping("/userinfo")
@RequiredArgsConstructor
public class UserinfoController {
private final UserinfoService userinfoService;
//예외 처리 메소드를 사용해 예외 처리 기능을 구현하고 인터셉터를 사용해 권한 관련 처리 기능 구현
// => 요청 처리 메소드에서는 예외 처리 및 권한 관련 명령 미작성
/*
@RequestMapping(value = "/write", method = RequestMethod.GET)
public String write(HttpSession session) {
Userinfo loginUserinfo=(Userinfo)session.getAttribute("loginUserinfo");
//페이지를 요청한 사용자가 비로그인 사용자이거나 관리자가 아닌 경우 인위적 예외 발생
if(loginUserinfo == null || loginUserinfo.getAuth() != 9) {
throw new BadRequestException("비정상적인 방법으로 페이지를 요청 하였습니다.");
}
return "userinfo/user_write";
}
*/
@RequestMapping(value = "/write", method = RequestMethod.GET)
public String write() {
return "userinfo/user_write";
}
//회원정보를 전달받아 USERINFO 테이블의 행으로 삽입하고 로그인 페이지를 요청할 수 있는
//URL 주소를 반환하는 요청 처리 메소드
@RequestMapping(value = "/write", method = RequestMethod.POST)
public String write(@ModelAttribute Userinfo userinfo, Model model) {
//매개변수로 전달받은 회원정보의 아이디가 중복될 경우 ExistsUserinfoException 발생
userinfoService.addUserinfo(userinfo);
return "redirect:/userinfo/login";
}
//인증정보를 입력받기 위한 JSP 문서의 뷰이름을 반환하는 요청 처리 메소드
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String login() {
return "userinfo/user_login";
}
//인증정보를 전달받아 USERINFO 테이블에 저장된 행을 검색하여 로그인 처리하고 환영메세지를
//출력하는 JSP 문서의 뷰이름 반환하는 요청 처리 메소드
// => 로그인 처리 : 인증 성공시 세션에 권한 관련 정보(회원정보)를 속성값으로 저장
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(@ModelAttribute Userinfo userinfo, Model model, HttpSession session) {
//매개변수로 전달받은 회원정보로 인증이 실패한 경우 LoginAuthFailException 발생
Userinfo authUserinfo=userinfoService.loginAuth(userinfo);
session.setAttribute("loginUserinfo", authUserinfo);
return "userinfo/user_login";
}
//로그아웃 처리하고 로그인 페이지를 요청할 수 있는 URL 주소를 반환하는 요청 처리 메소드
@RequestMapping("/logout")
public String logout(HttpSession session) {
//session.removeAttribute("loginUserinfo");
session.invalidate();
return "redirect:/userinfo/login";
}
//USERINFO 테이블에 저장된 모든 행을 검색하여 Request Scope 속성값으로 저장하고 회원목록을
//출력하는 JSP 문서의 뷰이름을 반환하는 요청 처리 메소드
// => 로그인 사용자만 요청 가능한 페이지로 설정
@RequestMapping("/list")
public String list(Model model) {
model.addAttribute("userinfoList", userinfoService.getUserinfoList());
return "userinfo/user_list";
}
//아이디를 전달받아 USERINFO 테이블에 저장된 행을 검색하여 Request Scope 속성값으로 저장하고
//회원정보를 출력하는 JSP 문서의 뷰이름을 반환하는 요청 처리 메소드
// => 로그인 사용자만 요청 가능한 페이지로 설정
@RequestMapping("/view")
public String view(@RequestParam String userid, Model model) {
model.addAttribute("userinfo", userinfoService.getUserinfo(userid));
return "userinfo/user_view";
}
//아이디를 전달받아 USERINFO 테이블에 저장된 행을 검색하여 Request Scope 속성값으로 저장하고
//회원정보를 변경하는 JSP 문서의 뷰이름을 반환하는 요청 처리 메소드
// => 관리자만 요청 가능한 페이지로 설정
@RequestMapping(value = "/modify", method = RequestMethod.GET)
public String modify(@RequestParam String userid, Model model) {
model.addAttribute("userinfo", userinfoService.getUserinfo(userid));
return "userinfo/user_modify";
}
//변경할 회원정보를 전달받아 USERINFO 테이블에 저장된 행을 변경하고 회원정보 출력 페이지를
//요청할 수 있는 URL 주소를 반환하는 요청 처리 메소드
@RequestMapping(value = "/modify", method = RequestMethod.POST)
public String modify(@ModelAttribute Userinfo userinfo, HttpSession session) {
userinfoService.modifyUserinfo(userinfo);
//로그인 사용자와 변경 처리된 사용자가 동일한 경우 세션에 저장된 권한 관련 속성값 변경
Userinfo loginUserinfo=(Userinfo)session.getAttribute("loginUserinfo");
if(loginUserinfo.getUserid().equals(userinfo.getUserid())) {
session.setAttribute("loginUserinfo", userinfoService.getUserinfo(userinfo.getUserid()));
}
return "redirect:/userinfo/view?userid="+userinfo.getUserid();
}
//아이디를 전달받아 USERINFO 테이블에 저장된 행을 삭제하고 회원목록 출력 페이지를 요청할
//수 있는 URL 주소를 반환하는 요청 처리 메소드
// => 관리자만 요청 가능한 페이지로 설정
@RequestMapping("/remove")
public String remove(@RequestParam String userid, HttpSession session) {
Userinfo loginUserinfo=(Userinfo)session.getAttribute("loginUserinfo");
userinfoService.removeUserinfo(userid);
//로그인 사용자와 삭제 처리된 회원정보의 아이디가 동일한 경우 로그아웃 페이지로
//리다이렉트 이동 처리
if(loginUserinfo.getUserid().equals(userid)) {
return "redirect:/userinfo/logout";
}
return "redirect:/userinfo/list";
}
}
/userinfo/write 부분만 봐도 요청 처리 메소드에서 예외 처리를 하지 않으니 코드가 확 줄은 것을 알 수 있다.
이 방법을 사용할 것인지는 선택해야될 거 같다. 너무 많이 줄인다고 좋은 건 아니라고 생각한다.