https://o5e2o5.tistory.com/222
- 기존에 그냥 MVC패턴으로 만든 것을 springMVC를 이용해 다시 만들 것임
- 기존에 만들었던 기능에 보안 처리 하는 방법, 예외 처리 하는 방법 추가할 것임
01. 테이블, DTO
🖤[테이블] USERINFO
desc userinfo
🖤[DTO] Userinfo.java
package xyz.itwill10.dto;
import lombok.Data;
//desc userinfo
/*
이름 널? 유형
-------- -------- -------------
USERID NOT NULL VARCHAR2(100)
PASSWORD VARCHAR2(100)
NAME VARCHAR2(200)
EMAIL VARCHAR2(300)
STATUS NUMBER(1)
*/
@Data
public class Userinfo {
private String userid;
private String password;
private String name;
private String email;
private int status;
}
02. Mapper바인딩
💛[Mapper] UserinfoMapper.xml
<?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.itwill10.mapper.UserinfoMapper">
<insert id="insertUserinfo">
insert into userinfo values(#{userid},#{password},#{name},#{email},#{status})
</insert>
<!-- 전달값이 있을 경우 변경해라! - 동적 SQL -->
<update id="updateUserinfo">
update userinfo
<set>
<if test="password!=null and password!=''">
password=#{password},
</if>
<if test="name!=null and name!=''">
name=#{name},
</if>
<if test="email!=null and email!=''">
email=#{email},
</if>
<if test="status==1 or status==9">
status=#{status},
</if>
</set>
where userid=#{userid}
</update>
<delete id="deleteUserinfo">
delete from userinfo where userid=#{userid}
</delete>
<select id="selectUserinfo" resultType="Userinfo">
select * from userinfo where userid=#{userid}
</select>
<select id="selectUserinfoList" resultType="Userinfo">
select * from userinfo order by userid
</select>
</mapper>
💛[Mapper] UserinfoMapper.java
package xyz.itwill10.mapper;
import java.util.List;
import xyz.itwill10.dto.Userinfo;
public interface UserinfoMapper {
int insertUserinfo(Userinfo userinfo);
int updateUserinfo(Userinfo userinfo);
int deleteUserinfo(String userid);
Userinfo selectUserinfo(String userid);
List<Userinfo> selectUserinfoList();
}
03. @Repository
🖤[DAO] (부모) UserinfoDAO.java
package xyz.itwill10.dao;
import java.util.List;
import xyz.itwill10.dto.Userinfo;
public interface UserinfoDAO {
int insertUserinfo(Userinfo userinfo);
int updateUserinfo(Userinfo userinfo);
int deleteUserinfo(String userid);
Userinfo selectUserinfo(String userid);
List<Userinfo> selectUserinfoList();
}
🖤[DAO] (자식) UserinfoDAOImpl.java
package xyz.itwill10.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import lombok.RequiredArgsConstructor;
import xyz.itwill10.dto.Userinfo;
import xyz.itwill10.mapper.UserinfoMapper;
@Repository
@RequiredArgsConstructor
public class UserinfoDAOImpl implements UserinfoDAO {
private final SqlSession sqlSession;
@Override
public int insertUserinfo(Userinfo userinfo) {
return sqlSession.getMapper(UserinfoMapper.class).insertUserinfo(userinfo);
}
@Override
public int updateUserinfo(Userinfo userinfo) {
return
}
@Override
public int deleteUserinfo(String userid) {
return sqlSession.getMapper(UserinfoMapper.class).deleteUserinfo(userid);
}
@Override
public Userinfo selectUserinfo(String userid) {
return sqlSession.getMapper(UserinfoMapper.class).selectUserinfo(userid);
}
@Override
public List<Userinfo> selectUserinfoList() {
return sqlSession.getMapper(UserinfoMapper.class).selectUserinfoList();
}
}
04. @Service
🌈 암호화 라이브러리 빌드처리
추가로 알면 좋은 라이브러리
🖤[Service] (부모) UserinfoService.java
package xyz.itwill10.service;
import java.util.List;
import xyz.itwill10.dto.Userinfo;
import xyz.itwill10.exception.ExistUserinfoException;
import xyz.itwill10.exception.LoginAuthFailExecption;
import xyz.itwill10.exception.UserinfoNotFoundException;
public interface UserinfoService {
void addUserinfo(Userinfo userinfo) throws ExistUserinfoException;
//해당하는 아이디의 회원정보를 검색했을 때 없을 경우 검색, 삭제, 변경이 안되므로 그거에 대한 예외처리 필요
void modifyUserinfo(Userinfo userinfo) throws UserinfoNotFoundException;
void removeUserinfo(String userid) throws UserinfoNotFoundException;
Userinfo getUserinfo(String userid) throws UserinfoNotFoundException;
List<Userinfo> getUserinfoList(); //예외를 만들어지 않아도 됨, 차라리 EL에서 empty 연산자 사용하기
Userinfo loginAuth(Userinfo userinfo) throws LoginAuthFailException;
}
🖤[Service] (자식) UserinfoServiceImpl.java
- 서비스 클래스의 메소드
- 서비스 클래스의 메소드는 원래 더 복잡함!
- 왜? 테이블 여러개 사용할 것이므로!!
- 원래는 복잡하지만 우선은 테이블 하나만 이용해서 간단히 작성함!!
- 실제 개발할 때와 다르니 주의
package xyz.itwill10.service;
import java.util.List;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.RequiredArgsConstructor;
import xyz.itwill10.dao.UserinfoDAO;
import xyz.itwill10.dto.Userinfo;
import xyz.itwill10.exception.ExistUserinfoException;
import xyz.itwill10.exception.LoginAuthFailException;
import xyz.itwill10.exception.UserinfoNotFoundException;
//🌈암호화 처리 기능을 사용하기 위한 방법
//=> Controller 클래스에서 만들어도 되지만, Service 클래스에서 만들어도 됨!
//step1.
//jbcrypt 라이브러리를 프로젝트에 빌드 처리 - 메이븐 : pm.xml
//[spring-security-core] [spring-security-web] [spring-security-config] 3개 빌드처리도 가능하지만,
//그러면 새 xml 파일 만들어야함ㅠㅠ
//step2.
//BCrypt.hashpw(String password, String salt)메소드를 호출하여 비밀번호의 암호화 처리
// => 매개변수로 비밀번호와 첨가물을 전달받아 암호화 처리 - 첨가물에 의해 비밀번호가 다르게 변환
// => salt(첨가물)에 의해 비밀번호가 싹 변경됨! salt를 알지 못하는 이상 암호화 알고리즘을 알아도 비밀번호를 절대 못알아냄
// => BCrypt 클래스 : 단방향 암호화 기능을 제공하는 BlowFish 알고리즘을 기반으로 설계된 암호화 처리 클래스 - 비밀번호를 저장할 목적으로 가장 많이 사용
// => BCrypt.gensalt(int log_bounds) : 첨가물(Salt - String)의 길이를 전달받아 첨가물을 생성하여 반환하는 메소드
// => 매개변수에 값을 전달하지 않을 경우 첨가물의 기본 길이는 [10]으로 자동 설정
//step3.
//BCrypt.checkpw(String plaintext, String hashed)로 암호화된 비밀번호를 비교하여 결과를 반환받아 저장하는 메소드
// => 매개변수로 일반 문자열(plaintext)과 암호화된 문자열(hashed)을 전달받아 비교하여 다른 경우 [false]를 반환하고
//같은 경우 [true]를 반환
//Service 클래스의 메소드는 데이타 처리 시 발생되는 문제에 대한 인위적 예외 발생
// => 발생된 예외는 Controller 클래스의 요청 처리 메소드에서 처리되도록 예외 전달
@Service
@RequiredArgsConstructor
public class UserinfoServiceImpl implements UserinfoService {
private final UserinfoDAO userinfoDAO; //인젝션처리
//addUserinfo - ExistUserinfoException 예외 전달
//insert, delete, update 하는 명령어는 ROLLBACK 처리 필요하므로 반드시 @Transactional 설정하기!!
@Transactional
@Override
public void addUserinfo(Userinfo userinfo) throws ExistUserinfoException {
//전달받은 회원정보의 아이디가 기존 회원정보의 아이디와 중복된 경우
if(userinfoDAO.selectUserinfo(userinfo.getUserid())!=null){
//사용자 정의 예외 클래스로 인위적 예외 발생
// => "예외를 명확하게 구분"하고 예외 처리 시 필요값을 저장하여 전달하기 위한 사용자 정의 예외클래스 작성
// => Front Controller도 명확한 예외를 알 수 있음
throw new ExistUserinfoException("이미 사용 중인 아이디를 입력 하였습니다.", userinfo);
}
//삽입 전 전달받은 회원정보의 비밀번호는 암호화 처리하여 필드값 저장
// => 전달받은 회원정보의 비밀번호를 암호화 처리하여 필드값으로 변경하는 명령은 Controller 클래스의 요청 처리 메소드에서 작성 가능
String hashedPassword = BCrypt.hashpw(userinfo.getPassword(),BCrypt.gensalt());
userinfo.setPassword(hashedPassword); //암호화된 비밀번호로 필드값 변경
userinfoDAO.insertUserinfo(userinfo); //삽입처리
}
//modifyUserinfo - UserinfoNotFoundException 예외 전달
@Transactional
@Override
public void modifyUserinfo(Userinfo userinfo) throws UserinfoNotFoundException {
//전달받은 회원정보의 아이디로 기존 회원정보를 검색하여 검색결과가 없는 경우 - 즉, 변경할 회원정보가 없다!!
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); //변경처리
}
//removeUserinfo - UserinfoNotFoundException 예외 전달
@Transactional
@Override
public void removeUserinfo(String userid) throws UserinfoNotFoundException {
//전달받은 회원정보의 아이디로 기존 회원정보를 검색하여 검색결과가 없는 경우 - 즉, 삭제할 회원정보가 없다!!
if(userinfoDAO.selectUserinfo(userid)==null) {
throw new UserinfoNotFoundException("아이디의 회원정보가 존재하지 않습니다.");
}
userinfoDAO.deleteUserinfo(userid); //삭제처리
}
//getUserinfo - UserinfoNotFoundException 예외 전달
//=> select를 전달하는 메소드에는 @Transactional 필요없음
//=> 왜? COMMIT, ROLLBACK 처리 필요없으므로!!
@Override
public Userinfo getUserinfo(String userid) throws UserinfoNotFoundException {
//전달받은 아이디로 기존 회원정보를 검색하여 검색결과를 반환받아 저장
Userinfo userinfo=userinfoDAO.selectUserinfo(userid);
//검색된 회원정보가 없는 경우
if(userinfo==null) {
throw new UserinfoNotFoundException("아이디의 회원정보가 존재하지 않습니다.");
}
return userinfo;
}
//getUserinfoList - 예외 발생 딱히 없음.. 왜? 그냥 출력만 하는 메소드니까..
@Override
public List<Userinfo> getUserinfoList() {
return userinfoDAO.selectUserinfoList();
}
//loginAuth - LoginAuthFailException 예외 전달
//회원정보를 전달받아 인증 처리하기 위한 메소드
// => 예외가 발생된 경우 [인증 실패]로 메소드 종료
// => 예외가 발생되지 않은 경우 [인증 성공]으로 검색된 회원정보를 반환
@Override
public Userinfo loginAuth(Userinfo userinfo) throws LoginAuthFailException {
//전달받은 회원정보의 아이디로 기존 회원정보를 검색하여 검색결과를 반환받아 저장
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;
}
}
05. @Controller
🖤[Controller] UserinfoController.java
- url 주소로 값을 전달하는 법
- url 주소로 값을 전달받는 법
- Front Controller 에 의해 호출되는 메소드
- @RequestMapping : 요청 처리 메소드
- @ExceptionHandler : 예외 처리 메소드
package xyz.itwill10.controller;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import lombok.RequiredArgsConstructor;
import xyz.itwill10.dto.Userinfo;
import xyz.itwill10.exception.ExistUserinfoException;
import xyz.itwill10.exception.LoginAuthFailExecption;
import xyz.itwill10.exception.UserinfoNotFoundException;
import xyz.itwill10.service.UserinfoService;
@Controller
@RequestMapping("/userinfo")
@RequiredArgsConstructor
public class UserinfoController {
//필드 의존성 주입
private final UserinfoService userinfoService;
🤍[GET] /userinfo/write 요청 - 권한(AdminAuthInterceptor) + 예외 없음
- 권한 : 로그인 사용자 중 관리자만 요청 가능함
- 예외 : 없음
/*
//회원등록을 위해 회원정보를 입력받기 위한 뷰이름을 반환하는 요청 처리 메소드
// => 비로그인 사용자 또는 관리자가 아닌 사용자가 페이지를 요청한 경우 인위적 예외 발생
// => 예외 처리 메소드에 의해 예외 처리 - 에러 메세지를 출력하는 JSP 문서로 포워드 이동하여 응답
@RequestMapping(value = "/write", method = RequestMethod.GET)
public String write(HttpSession session) throws Exception {
//세션에 저장된 권한 관련 객체를 반환받아 저장
Userinfo loginUserinfo=(Userinfo)session.getAttribute("loginUserinfo");
//비로그인 사용자이거나 관리자가 아닌 경우
if(loginUserinfo==null || loginUserinfo.getStatus()!=9) {
throw new Exception("비정상적인 요청입니다.");
}
return "userinfo/user_write";
}
*/
//회원등록을 위해 회원정보를 입력받기 위한 뷰이름을 반환하는 요청 처리 메소드
// => 비로그인 사용자 또는 관리자가 아닌 사용자가 페이지 요청할 경우 권한 관련 인터셉터를 이용하여 처리
// => 권한 관련 인터셉터를 이용할 경우 요청 처리 메소드에서 권한 관련 명령 미작성 가능
@RequestMapping(value = "/write", method = RequestMethod.GET)
public String write() {
return "userinfo/user_write";
}
🤍[POST] /userinfo/write 요청 - 권한(AdminAuthInterceptor) + 예외(ExistUserinfoException)
- 권한 : 로그인 사용자 중 관리자만 요청 가능함
- 예외 : 전달받은 아이디가 이미 존재하는 아이디라는 예외 발생의 가능성
//=> 요청 처리 메소드에서는 예외 처리를 위해 앞으로 try~catch를 사용하지 않음!! 우리는 이제 예외처리메소드를 이용할 것임(ExceptionHandler)
/*
//회원정보를 전달받아 USERINFO 테이블에 삽입하고 로그인 페이지를 요청하기 위한 URL 주소를
//클라이언트에게 전달하는 요청 처리 메소드
// => UserinfoService 객체의 메소드 호출 시 예외 발생 가능 - try~catch 구문을 사용하여 예외 처리
// => try ~ catch 구문을 쓰면 예외를 잡아서 어떻게 처리할 지 알려주지만,
// => try ~ catch 구문을 쓰지 않고 예외를 전달하면 500 에러를 발생함
@RequestMapping(value = "/write", method = RequestMethod.POST)
public String write(@ModelAttribute Userinfo userinfo, Model model) {
try {
userinfoService.addUserinfo(userinfo);
} catch (ExistUserinfoException e) {
//뷰에서 출력하기 위해 ExistUserinfoException객체에 저장된 에러 메세지를 속성값으로 저장
model.addAttribute("message", e.getMessage());
//뷰에서 출력하기 위해 ExistUserinfoException객체에 저장된 회원정보(사용자입력값)을 속성값으로 저장
model.addAttribute("userinfo", userinfo);
//아이디 중복으로 예외가 발생된 경우 회원정보를 입력받기 위한 뷰이름을 반환
return "userinfo/user_write"; //한마디로 현재페이지 새로고침 느낌..?!
}
return "redirect:/userinfo/login";
}
*/
//회원정보를 전달받아 USERINFO 테이블에 삽입하고 로그인 페이지를 요청하기 위한 URL 주소를 클라이언트에게 전달하는 요청 처리 메소드
// => UserinfoService 객체의 메소드 호출 시 예외 발생 가능 - Front Controller에게 예외 전달
// => Front Controller는 전달받은 예외로 인해 500 에러코드 발생하여 클라이언트에게 전달
// => Front Controller는 해당 예외에 대한 ExceptionHandler 기능을 제공하는 메소드가
//작성된 경우 ExceptionHandler 기능의 메소드를 호출하여 예외 처리 가능
@RequestMapping(value = "/write", method = RequestMethod.POST)
public String write(@ModelAttribute Userinfo userinfo) throws ExistUserinfoException {
userinfoService.addUserinfo(userinfo);
return "redirect:/userinfo/login";
}
🤍[GET] /userinfo/login 요청 - 권한 없음 + 예외 없음
- 권한 : 없음
- 예외 : 없음
//로그인을 위해 인증정보를 입력받기 위한 뷰이름을 반환하는 요청 처리 메소드
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String login() /*throws Exception*/ {
return "userinfo/user_login";
}
🤍[POST] /userinfo/login 요청 - 권한 없음 + 예외(LoginAuthFailException)
- 권한 : 없음
- 예외 : 전달받은 아이디가 존재하지 않는 아이디라는 예외 발생의 가능성
//인증정보를 전달받아 로그인 처리 후 환영 메세지를 출력하는 뷰이름을 반환하는 요청 처리 메소드
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(@ModelAttribute Userinfo userinfo, HttpSession session) throws LoginAuthFailException {
//인증 실패시 LoginAuthFailException 발생하고 인증 성공시 검색된 회원정보 반환받아 저장
Userinfo authUserinfo=userinfoService.loginAuth(userinfo);
//세션에 권한 관련 정보를 속성값으로 저장
session.setAttribute("loginUserinfo", authUserinfo);
return "userinfo/user_login";
}
🤍/userinfo/list 요청 - 권한(LoginAuthInterceptor) + 예외 없음
- 권한 : 로그인 사용자만 요청 가능함
- 예외 : 없음
/*
//[핵심관심코드] : USERINFO 테이블에 저장된 모든 회원정보를 검색하여 속성값으로 저장하여 회원목록을 출력
//하는 뷰이름을 반환하는 요청 처리 메소드
//[횡단관심코드 - Interceptor클래스] : 비로그인 사용자가 페이지를 요청한 경우 인위적 예외 발생 - 예외 처리 메소드에 의해 예외 처리
@RequestMapping("/list")
public String list(Model model, HttpSession session) throws Exception {
Userinfo loginUserinfo=(Userinfo)session.getAttribute("loginUserinfo");
if(loginUserinfo==null) {//비로그인 사용자가 페이지를 요청한 경우
throw new Exception("비정상적인 요청입니다.");//인위적 예외 발생
}
model.addAttribute("userinfoList", userinfoService.getUserinfoList());
return "userinfo/user_list";
}
*/
//USERINFO 테이블에 저장된 모든 회원정보를 검색하여 속성값으로 저장하여 회원목록을 출력하는 뷰이름을 반환하는 요청 처리 메소드
// => 비로그인 사용자가 페이지를 요청할 경우 권한 관련 인터셉터를 이용하여 처리
@RequestMapping("/list")
public String list(Model model) {
model.addAttribute("userinfoList", userinfoService.getUserinfoList());
return "userinfo/user_list";
}
🤍/userinfo/view 요청 - 권한(LoginAuthInterceptor) + 예외(UserinfoNotFoundException)
- 권한 : 로그인 사용자만 요청 가능함
- 예외 : 전달받은 아이디가 존재하지 않는 아이디라는 예외 발생의 가능성
//아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보를 검색하여 속성값으로
//저장하여 회원정보를 출력하는 뷰이름을 반환하는 요청 처리 메소드
// => 비로그인 사용자가 페이지를 요청할 경우 권한 관련 인터셉터를 이용하여 처리
@RequestMapping("/view")
public String view(@RequestParam String userid, Model model) throws UserinfoNotFoundException {
model.addAttribute("userinfo", userinfoService.getUserinfo(userid));
return "userinfo/user_view";
}
🤍[GET] /userinfo/modify 요청 - 권한(AdminAuthInterceptor) + 예외(UserinfoNotFoundException)
- 권한 : 로그인 사용자 중 관리자만 요청 가능함
- 예외 : 전달받은 아이디가 존재하지 않는 아이디라는 예외 발생의 가능성
//아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보를 검색하여 속성값으로
//저장하여 변경할 회원정보를 입력받기 위한 뷰이름을 반환하는 요청 처리 메소드
// => 비로그인 사용자 또는 관리자가 아닌 사용자가 페이지 요청할 경우 권한 관련 인터셉터를 이용하여 처리
@RequestMapping(value = "/modify", method = RequestMethod.GET)
public String modify(@RequestParam String userid, Model model) throws UserinfoNotFoundException {
model.addAttribute("userinfo", userinfoService.getUserinfo(userid));
return "userinfo/user_modify";
}
🤍[POST] /userinfo/modify 요청 - 권한(AdminAuthInterceptor) + 예외(UserinfoNotFoundException)
- 권한 : 로그인 사용자 중 관리자만 요청 가능함
- 예외 : 전달받은 아이디가 존재하지 않는 아이디라는 예외 발생의 가능성
//회원정보를 전달받아 USERINFO 테이블에 저장된 회원정보를 변경하고 회원정보를 출력하는
//페이지를 요청하기 위한 URL 주소를 클라이언트에게 전달하는 요청 처리 메소드
// => 변경 처리 하기 위한 사용자가 로그인 사용자인 경우 세션에 저장된 권한 관련 정보 변경
@RequestMapping(value = "/modify", method = RequestMethod.POST)
public String modify(@ModelAttribute Userinfo userinfo,HttpSession session) throws UserinfoNotFoundException {
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/user_view?userid="+userinfo.getUserid();
}
🤍[POST] /userinfo/remove 요청 - 권한() + 예외(UserinfoNotFoundException)
- 권한 : 로그인 사용자 중 관리자만 요청 가능함
- 예외 : 전달받은 아이디가 존재하지 않는 아이디라는 예외 발생의 가능성
//아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보를 삭제하고 회원목록을
//출력하는 페이지를 요청하기 위한 URL 주소를 클라이언트에게 전달하는 요청 처리 메소드
// => 비로그인 사용자 또는 관리자가 아닌 사용자가 페이지 요청할 경우 권한 관련 인터셉터를 이용하여 처리
@RequestMapping("/remove")
public String remove(@RequestParam String userid, HttpSession session) throws UserinfoNotFoundException {
userinfoService.removeUserinfo(userid);
Userinfo loginUserinfo = (Userinfo)session.getAttribute("loginUserinfo");
//로그인 사용자가 삭제된 경우
if(loginUserinfo.getUserid().equals(userid)) {
return "redirect:userinfo/logout";
}
return "redirect:userinfo/list";
}
🤍 /userinfo/logout 요청 - 권한(LoginAuthInterceptor) + 예외 없음
- 권한 : 로그인 사용자만 요청 가능함
- 예외 : 없음
//로그아웃 처리 후 로그인 페이지를 요청하기 위한 URL 주소를 클라이언트에게 전달하는 요청 처리 메소드
@RequestMapping("/logout")
public String login(HttpSession session) {
//session.removeAttribute("loginUserinfo");
session.invalidate();
return "redirect:/userinfo/login";
}
🤍 예외 처리 메소드 (ExceptionHandler Method)
- 일반적으로 메세지를 출력하게 예외 처리 메소드 작성함
- 예외 처리 메소드가 있기 때문에 요청 처리 메소드에서 try ~ catch 구문을 쓸 필요가 없고, 그냥 메소드만 호출해서 사용
- 만약 요청 처리 메소드에서 예외가 발생한다면?? 예외를 전달하여 Front Controller가 예외를 호출해 알아서 처리할 수 있도록 메소드만 잘 작성해두기
- 예외처리는 try ~ catch로 절대 하지 않고, ExceptionHandler 이용할 것임
//예외 처리 메소드
//=> 주의) 작성 순서도 중요함 ExistUserinfoException -> -> ... -> Exception
// => Exception 예외는 try~catch 처럼 가장 마지막에 작성해야함 - 왜? 모든 예외를 다 잡으니까!!
//@ExceptionHandler : Controller 클래스의 메소드에 예외 처리 기능을 제공하도록 설정하는 어노테이션
// => Controller 클래스의 요청 처리 메소드에서 예외가 발생되어 Front Controller에게 전달된 경우 예외 관련 객체를 제공받아 예외 처리하기 위한 메소드 - ExceptionHandler Method
//value 속성 : 예외 처리하기 위한 클래스(Class 객체)를 속성값으로 설정
// => 다른 속성이 없는 경우 속성값만 설정 가능
//예외 처리 메소드에서 예외 처리를 위해 필요한 객체를 매개변수로 전달받아 사용 가능하며 뷰이름을 반환해 JSP 문서로 응답 처리 가능 - 리다이렉트 이동 가능
@ExceptionHandler(value = ExistUserinfoException.class) //ExistUserinfoException 클래스에서 처리할게!
public String userinfoExceptionHandler(ExistUserinfoException exception, Model model) {
model.addAttribute("message", exception.getMessage()); //저장해서 user_write.jsp로 보낼게
model.addAttribute("userinfo", exception.getUserinfo());
return "userinfo/user_write";
}
@ExceptionHandler(LoginAuthFailExecption.class)
public String userinfoExceptionHandler(LoginAuthFailException exception, Model model) {
model.addAttribute("message", exception.getMessage());
model.addAttribute("userid",exception.getUserid());
return "userinfo/user_login";
}
@ExceptionHandler(UserinfoNotFoundException.class)
public String userinfoExceptionHandler(UserinfoNotFoundException exception) {
return "userinfo/user_error";
}
/*
@ExceptionHandler(value = Exception.class) //Exception 클래스에서 처리할게! (모든 예외를 다 잡을 예정)
public String userinfoExceptionHandler() {
return "userinfo/user_error";
}
*/
}
06. VIEW
💚[JSP] user_write.jsp - 회원등록 입력페이지
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="<http://java.sun.com/jsp/jstl/core>"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<http://www.w3.org/TR/html4/loose.dtd>">
<html>
<head>
<title>SPRING</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel=stylesheet href="<c:url value="/css/user.css"/>" type="text/css">
<script language="JavaScript">
function userCreate() {
if ( f.userid.value == "" ) {
alert("아이디를 입력하십시요.");
f.userid.focus();
return;
}
if ( f.password.value == "" ) {
alert("비밀번호를 입력하십시요.");
f.password.focus();
return;
}
if ( f.name.value == "" ) {
alert("이름을 입력하십시요.");
f.name.focus();
return;
}
f.action = "<c:url value="/userinfo/write"/>";
f.submit();
}
</script>
</head>
<body bgcolor=#FFFFFF text=#000000 leftmargin=0 topmargin=0 marginwidth=0 marginheight=0>
<br>
<table width=780 border=0 cellpadding=0 cellspacing=0>
<tr>
<td width="20"></td>
<td style="color: red;">${message }</td>
</tr>
<tr>
<td width="20"></td>
<td>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td bgcolor="f4f4f4" height="22"> <b>회원관리 - 회원등록</b></td>
</tr>
</table>
<br>
<form name="f" method="post">
<table border="0" cellpadding="0" cellspacing="1" width="590" bgcolor="BBBBBB">
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">아이디</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="text" style="width:150" name="userid" value="${userinfo.userid }">
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">비밀번호</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="password" style="width:150" name="password" value="${userinfo.password }">
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">이름</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="text" style="width:240" name="name" value="${userinfo.name }">
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">이메일</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="text" style="width:240" name="email" value="${userinfo.email }">
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">회원등급</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<select name="status">
<option value="1" <c:if test="${userinfo.status == 1 }">selected</c:if>>일반회원</option>
<option value="9" <c:if test="${userinfo.status == 9 }">selected</c:if>>관리자</option>
</select>
</td>
</tr>
</table>
</form>
<br>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td align=center>
<input type="button" value="회원등록" onClick="userCreate();">
<input type="button" value="로그인" onClick="location.href='<c:url value="/userinfo/login"/>';">
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
💚[JSP] user_login.jsp - 로그인 입력페이지
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="<http://java.sun.com/jsp/jstl/core>"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<http://www.w3.org/TR/html4/loose.dtd>">
<html>
<head>
<title>SPRING</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel=stylesheet href="<c:url value="/css/user.css"/>" type="text/css">
<script language="JavaScript">
function userLogin() {
if ( f.userid.value == "" ) {
alert("아이디를 입력하십시요.");
f.userid.focus();
return;
}
if ( f.password.value == "" ) {
alert("비밀번호를 입력하십시요.");
f.password.focus();
return;
}
f.action = "<c:url value="/userinfo/login"/>";
f.submit();
}
</script>
</head>
<body bgcolor=#FFFFFF text=#000000 leftmargin=0 topmargin=0 marginwidth=0 marginheight=0>
<br>
<table width=780 border=0 cellpadding=0 cellspacing=0>
<tr>
<td width="20"></td>
<td style="color: red;">${message }</td>
</tr>
<tr>
<td width="20"></td>
<td>
<!--contents-->
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td bgcolor="f4f4f4" height="22"> <b>회원관리 - 로그인</b></td>
</tr>
</table>
<br>
<c:choose>
<c:when test="${empty(loginUserinfo) }"><%-- 비로그인 사용자인 경우 --%>
<!-- login Form -->
<form name="f" method="post">
<table border="0" cellpadding="0" cellspacing="1" width="590" bgcolor="BBBBBB">
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">사용자 아이디</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="text" style="width:150" name="userid" value="${userid }">
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">비밀번호</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="password" style="width:150" name="password">
</td>
</tr>
</table>
</form>
<br>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td align=center>
<input type="button" value="로그인" onClick="userLogin();">
</td>
</tr>
</table>
</c:when>
<c:otherwise><%-- 로그인 사용자인 경우 --%>
<table border="0" cellpadding="0" cellspacing="1" width="590" bgcolor="BBBBBB">
<tr>
<td align=center bgcolor="E6ECDE" height="22">
${loginUserinfo.name }님, 환영합니다.
</td>
</tr>
</table>
<br>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td align=center>
<button type="button" onclick="location.href='<c:url value="/userinfo/list"/>';">회원목록</button>
<button type="button" onclick="location.href='<c:url value="/userinfo/logout"/>';">로그아웃</button>
<c:if test="${loginUserinfo.status == 9 }">
<button type="button" onclick="location.href='<c:url value="/userinfo/write"/>';">회원등록</button>
</c:if>
</td>
</tr>
</table>
</c:otherwise>
</c:choose>
</td>
</tr>
</table>
</body>
</html>
💚[JSP] user_list.jsp - 회원목록 출력페이지
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="<http://java.sun.com/jsp/jstl/core>"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<http://www.w3.org/TR/html4/loose.dtd>">
<html>
<head>
<title>SPRING</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel=stylesheet href="<c:url value="/css/user.css"/>" type="text/css">
</head>
<body bgcolor=#FFFFFF text=#000000 leftmargin=0 topmargin=0 marginwidth=0 marginheight=0>
<br>
<table width=780 border=0 cellpadding=0 cellspacing=0>
<tr>
<td width="20"></td>
<td>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td bgcolor="f4f4f4" height="22"> <b>회원관리 - 회원목록</b></td>
</tr>
</table>
<br>
<table border="0" cellpadding="0" cellspacing="1" width="590" bgcolor="BBBBBB">
<tr>
<td width=190 align=center bgcolor="E6ECDE" height="22">아이디</td>
<td width=200 align=center bgcolor="E6ECDE">이름</td>
<td width=200 align=center bgcolor="E6ECDE">이메일</td>
</tr>
<c:forEach var="userinfo" items="${userinfoList }">
<tr>
<td width=190 align=center bgcolor="ffffff" height="20">
${userinfo.userid }
</td>
<td width=200 align=center bgcolor="ffffff">
<a href="<c:url value="/userinfo/view"/>?userid=${userinfo.userid }" class="user">
${userinfo.name }
</a>
</td>
<td width=200 align=center bgcolor="ffffff">
${userinfo.email }
</td>
</tr>
</c:forEach>
</table>
<br>
<table border="0" cellpadding="0" cellspacing="1" width="590">
<tr>
<td align="right">
<c:if test="${loginUserinfo.status == 9 }">
<input type="button" value="회원등록" onclick="location.href='<c:url value="/userinfo/write"/>';"/>
</c:if>
<input type="button" value="로그아웃" onclick="location.href='<c:url value="/userinfo/logout"/>';"/>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
💚[JSP] user_view.jsp - 회원정보 출력페이지
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="<http://java.sun.com/jsp/jstl/core>"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<http://www.w3.org/TR/html4/loose.dtd>">
<html>
<head>
<title>SPRING</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel=stylesheet href="<c:url value="/css/user.css"/>" type="text/css">
<script language="JavaScript">
function userRemove(userid) {
if (confirm("정말로 삭제 하시겠습니까?") ) {
location.href='<c:url value="/userinfo/remove"/>?userid='+userid;
}
}
</script>
</head>
<body bgcolor=#FFFFFF text=#000000 leftmargin=0 topmargin=0 marginwidth=0 marginheight=0>
<br>
<table width=780 border=0 cellpadding=0 cellspacing=0>
<tr>
<td width="20"></td>
<td>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td bgcolor="f4f4f4" height="22"> <b>회원관리 - 회원정보</b></td>
</tr>
</table>
<br>
<table border="0" cellpadding="0" cellspacing="1" width="590" bgcolor="BBBBBB">
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">아이디</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
${userinfo.userid }
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">이름</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
${userinfo.name }
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">이메일</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
${userinfo.email }
</td>
</tr>
</table>
<br>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td align=center>
<c:if test="${loginUserinfo.status == 9 }">
<input type="button" value="수정" onClick="location.href='<c:url value="/userinfo/modify"/>?userid=${userinfo.userid}';">
<input type="button" value="삭제" onClick="userRemove('${userinfo.userid}');">
</c:if>
<input type="button" value="목록" onClick="location.href='<c:url value="/userinfo/list"/>';">
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
💚[JSP] user_modify.jsp - 회원정보 수정페이지
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="<http://java.sun.com/jsp/jstl/core>"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<http://www.w3.org/TR/html4/loose.dtd>">
<html>
<head>
<title>SPRING</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel=stylesheet href="<c:url value="/css/user.css"/>" type="text/css">
<script language="JavaScript">
function userModify() {
if ( f.name.value == "" ) {
alert("이름을 입력하십시요.");
f.name.focus();
return false;
}
f.action = "<c:url value="/userinfo/modify"/>";
f.submit();
}
</script>
</head>
<body bgcolor=#FFFFFF text=#000000 leftmargin=0 topmargin=0 marginwidth=0 marginheight=0>
<br>
<table width=780 border=0 cellpadding=0 cellspacing=0>
<tr>
<td width="20"></td>
<td>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td bgcolor="f4f4f4" height="22"> <b>회원관리 - 회원정보수정</b></td>
</tr>
</table>
<br>
<form name="f" method="post">
<input type="hidden" name="userid" value="${userinfo.userid }">
<table border="0" cellpadding="0" cellspacing="1" width="590" bgcolor="BBBBBB">
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">아이디</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
${userinfo.userid }
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">비밀번호</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="password" style="width:150" name="password">
<span style="color: red;">** 비밀번호를 변경하지 않을 경우 입력하지 마세요. **</span>
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">이름</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="text" style="width:240" name="name" value="${userinfo.name }">
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">이메일 주소</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="text" style="width:240" name="email" value="${userinfo.email }">
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">회원등급</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<select name="status">
<option value="1" <c:if test="${userinfo.status == 1 }">selected</c:if>>일반회원</option>
<option value="9" <c:if test="${userinfo.status == 9 }">selected</c:if>>관리자</option>
</select>
</td>
</tr>
</table>
</form>
<br>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td align=center>
<input type="button" value="수정" onClick="userModify();">
<input type="button" value="목록" onClick="location.href='<c:url value="/userinfo/list"/>';">
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
💚[JSP] user_error.jsp - 에러페이지
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="<http://java.sun.com/jsp/jstl/core>"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
<style type="text/css">
body {
text-align: center;
}
.message {
color: red;
font-size: 1.5em;
}
</style>
</head>
<body>
<h1>에러페이지</h1>
<hr>
<p class="message">프로그램 실행에 예기치 못한 오류가 발생 하였거나 비정상적 방법으로
프로그램을 요청하여 오류가 발생 하였습니다.</p>
<button type="button" onclick="location.href='<c:url value="/userinfo/login"/>';">로그인 페이지 이동</button>
</body>
</html>
'framework > spring mvc 웹사이트제작법' 카테고리의 다른 글
[springMVC웹] 14. REST API 게시판 프로그램 (0) | 2024.08.05 |
---|---|
[springMVC웹] 13. 요청 처리 메소드에서 JSON으로 응답하는 법 (0) | 2024.08.05 |
[springMVC웹]11. 트랜잭션 매니저 이용하는 법 @Transactional (0) | 2024.08.05 |
[springMVC웹] 10. 모듈 테스트하는 법 (@RunWith, @ContextConfiguration, @WebAppConfiguration, @FixMethodOrder) (0) | 2024.08.05 |
[springMVC웹] 9. TilesView 관련 환경설정파일 - tiles.xml (0) | 2024.08.05 |