1. 유효성 검사 V1
1) build.gradle 에 추가
implementation 'org.springframework.boot:spring-boot-starter-validation'2) BoardRequest.java
package com.example.boardv1.board;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
public class BoardRequest {
// 책임 : 클라이언트(브라우저)의 요청 데이터를 저장하는 클래스
@Data
public static class SaveOrUpdateDTO {
@NotBlank(message = "제목을 입력해주세요")
private String title;
@NotBlank(message = "내용을 입력해주세요")
private String content;
}
}3) UserRequest.java
package com.example.boardv1.user;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
public class UserRequest {
@Data
public static class JoinDTO {
@NotBlank(message = "유저네임을 입력해주세요")
@Size(min = 3, max = 20, message = "유저네임은 3~20자로 입력해주세요")
private String username;
@NotBlank(message = "비밀번호을 입력해주세요")
@Size(min = 4, max = 20, message = "비밀번호는 4~20자로 입력해주세요")
private String password;
@NotBlank(message = "이메일 형식이 올바르지 않습니다")
private String email;
}
@Data
public static class LoginDTO {
@NotBlank(message = "유저네임을 입력해주세요")
private String username;
@NotBlank(message = "비밀번호을 입력해주세요")
private String password;
}
}4) ReplyRequest.java
package com.example.boardv1.reply;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
public class ReplyRequest {
@Data
public static class SaveDTO {
private Integer boardId;
@NotBlank(message = "댓글 내용을 입력하세요")
private String comment;
}
@Data
public static class DeleteDTO {
private Integer boardId;
}
}
5) BoardController.java
package com.example.boardv1.board;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.example.boardv1._core.errors.ex.Exception400;
import com.example.boardv1._core.errors.ex.Exception401;
import com.example.boardv1._core.errors.ex.Exception500;
import com.example.boardv1.user.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor // final이 적혀있는 애로 생성자 만들어줌
@Controller // @Controller 적어야 리턴값이 파일이 됨 (외부진입점)
public class BoardController {
private final BoardService boardService;
private final HttpSession session;
// title : title=title7&content=content7 (x-www-form)
@PostMapping("/boards/save")
public String save(@Valid BoardRequest.SaveOrUpdateDTO reqDTO, Errors errors) { // new해서 넣어줌! 필드가 많을 때 상태만 추가하면 되기 때문에 매우 편함! 재사용 가능!(필드명 잘 적어야 함)
// 유효성 검사 실패 시
if (errors.hasErrors()) {
throw new Exception400(errors.getAllErrors().get(0).getDefaultMessage());
}
// 인증(v) 권한(x)
// 인증
User sessionUser = (User) session.getAttribute("sessionUser");
if (sessionUser == null)
throw new Exception401("인증되지 않았습니다.");
boardService.게시글쓰기(reqDTO.getTitle(), reqDTO.getContent(), sessionUser.getId());
return "redirect:/";
}
// body : title=제목&content=내용
@PostMapping("/boards/{id}/update")
public String update(@PathVariable("id") int id, @Valid BoardRequest.SaveOrUpdateDTO reqDTO, Errors errors) {
// 유효성 검사 실패 시
if (errors.hasErrors()) {
throw new Exception400(errors.getAllErrors().get(0).getDefaultMessage());
}
// 인증(v) 권한(v)
// 인증
User sessionUser = (User) session.getAttribute("sessionUser");
if (sessionUser == null)
throw new Exception401("인증되지 않았습니다.");
boardService.게시글수정(id, reqDTO.getTitle(), reqDTO.getContent(), sessionUser.getId());
return "redirect:/boards/" + id;
}
@GetMapping("/")
public String index(HttpServletRequest req) {
List<Board> list = boardService.게시글목록();
req.setAttribute("models", list);
return "index";
}
@GetMapping("/boards/save-form")
public String saveForm() {
// 인증(v) 권한(x)
// 인증
User sessionUser = (User) session.getAttribute("sessionUser");
if (sessionUser == null)
throw new Exception401("인증되지 않았습니다.");
return "board/save-form";
}
@GetMapping("/boards/{id}/update-form")
public String updateForm(@PathVariable("id") int id, HttpServletRequest req) {
// 인증(v) 권한(v)
// 인증
User sessionUser = (User) session.getAttribute("sessionUser");
if (sessionUser == null)
throw new Exception401("인증되지 않았습니다.");
Board board = boardService.수정폼게시글정보(id, sessionUser.getId());
req.setAttribute("model", board);
return "board/update-form";
}
@GetMapping("/boards/{id}")
public String detail(@PathVariable("id") int id, HttpServletRequest req) {
User sessionUser = (User) session.getAttribute("sessionUser"); // Object타입으로 반환하기 때문에 다운캐스팅해야 함
Integer sessionUserId = sessionUser == null ? null : sessionUser.getId();
BoardResponse.DetailDTO dto = boardService.상세보기(id, sessionUserId);
req.setAttribute("model", dto);
return "board/detail"; // mustache 파일의 경로
}
@PostMapping("/boards/{id}/delete")
public String delete(@PathVariable("id") int id) {
// 인증(v) 권한(v)
// 인증
User sessionUser = (User) session.getAttribute("sessionUser");
if (sessionUser == null)
throw new Exception401("인증되지 않았습니다.");
try {
boardService.게시글삭제(id, sessionUser.getId());
} catch (Exception e) {
throw new Exception500("댓글이 있는 게시글을 삭제할 수 없습니다");
}
return "redirect:/";
}
@GetMapping("/api/boards/{id}")
public @ResponseBody BoardResponse.DetailDTO apiDetail(@PathVariable("id") int id) {
User sessionUser = (User) session.getAttribute("sessionUser");
Integer sessionUserId = sessionUser == null ? null : sessionUser.getId();
BoardResponse.DetailDTO dto = boardService.상세보기(id, sessionUserId);
return dto;
}
}
6) UserController.java
package com.example.boardv1.user;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import com.example.boardv1._core.errors.ex.Exception400;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Controller
public class UserController {
private final UserService userService;
private final HttpSession session;
@GetMapping("/logout")
public String logout(){
session.invalidate(); // sessionKey 삭제
return "redirect:/";
}
// 조회인데, 예외로 post 요청
@PostMapping("/login")
public String login(@Valid UserRequest.LoginDTO reqDTO, Errors errors, HttpServletResponse resp) {
// 유효성 검사 실패 시
if (errors.hasErrors()) {
throw new Exception400(errors.getAllErrors().get(0).getDefaultMessage());
}
// HttpSession session = req.getSession();
User sessionUser = userService.로그인(reqDTO.getUsername(), reqDTO.getPassword());
session.setAttribute("sessionUser", sessionUser);
// http Response header에 Set-Cookie: sessionKey 저장되서 응답됨.
Cookie cookie = new Cookie("username", sessionUser.getUsername());
cookie.setHttpOnly(false);
resp.addCookie(cookie);
return "redirect:/";
}
@PostMapping("/join")
public String join(@Valid UserRequest.JoinDTO reqDTO, Errors errors){
// 유효성 검사 실패 시
if (errors.hasErrors()) {
throw new Exception400(errors.getAllErrors().get(0).getDefaultMessage());
}
userService.회원가입(reqDTO.getUsername(), reqDTO.getPassword(), reqDTO.getEmail());
return "redirect:/login-form";
}
@GetMapping("/login-form")
public String loginForm(){
return "user/login-form";
}
@GetMapping("/join-form")
public String joinForm(){
return "user/join-form";
}
}7) ReplyController.java
package com.example.boardv1.reply;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.example.boardv1._core.errors.ex.Exception400;
import com.example.boardv1.user.User;
import jakarta.servlet.http.HttpSession;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Controller
public class ReplyController {
private final ReplyService replyService;
private final HttpSession session;
@PostMapping("/replies/save")
public String save(@Valid ReplyRequest.SaveDTO reqDTO, Errors errors){
// 유효성 검사 실패 시
if (errors.hasErrors()) {
throw new Exception400(errors.getAllErrors().get(0).getDefaultMessage());
}
// 인증
User sessionUser = (User) session.getAttribute("sessionUser");
if (sessionUser == null)
throw new RuntimeException("인증되지 않았습니다.");
int sessionUserId = sessionUser.getId();
replyService.댓글등록(sessionUserId, reqDTO.getBoardId(), reqDTO.getComment());
return "redirect:/boards/" + reqDTO.getBoardId();
}
// /replies/5/delete?boardId=2
@PostMapping("/replies/{id}/delete")
public String delete(@PathVariable("id") int id, @RequestParam("boardId") int boardId){
// 인증
User sessionUser = (User) session.getAttribute("sessionUser");
if (sessionUser == null)
throw new RuntimeException("인증되지 않았습니다.");
replyService.댓글삭제(id, sessionUser.getId());
return "redirect:/boards/" + boardId;
}
}Share article