
1. UserRepository에서
package shop.mtcoding.blog.user;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import shop.mtcoding.blog.board.BoardResponse;
import java.util.List;
@Repository // IoC에 new하는 방법
public class UserRepository {
    // DB에 접근할 수 있는 매니저 객체
    // 스프링이 만들어서 IoC에 넣어둔다.
    // DI에서 꺼내 쓰기만 하면된다.
    private EntityManager em; // 컴포지션
    // 생성자 주입 (DI 코드)
    public UserRepository(EntityManager em) {
        this.em = em;
    }
    @Transactional // db에 write 할때는 필수
    public void save(UserRequest.JoinDTO requestDTO){
        Query query = em.createNativeQuery("insert into user_tb(username, password, email, created_at) values(?,?,?, now())");
        query.setParameter(1, requestDTO.getUsername());
        query.setParameter(2, requestDTO.getPassword());
        query.setParameter(3, requestDTO.getEmail());
        query.executeUpdate();
    }
    public User findByUsernameAndPassword(UserRequest.LoginDTO requestDTO) {
        Query query = em.createNativeQuery("select * from user_tb where username=? and password=?", User.class); // 알아서 매핑해줌
        query.setParameter(1, requestDTO.getUsername());
        query.setParameter(2, requestDTO.getPassword());
        try { // 내부적으로 터지면 터지는 위치를 찾아서 내가 잡으면 됨
            User user = (User) query.getSingleResult();
            return user;
        } catch (Exception e) {
            return null;
        }
    }
}2. _core.handler 패키지 생성
CustomExceptionHandler 클래스 생성
package shop.mtcoding.blog._core.handler;
public class CustomExceptionHandler {
}
o o o o o
5번째에서 오류가 터지면 null이 처리하는 첫번쨰 레이어까지 와야함 -. 매우 복잡해짐
가까이에 있으면 상관없음
깊숙하면 문제가 됨
따로 exceptionhandler 클래스를 하나 만들어서
try/catch가 터지면 직접 처리하지 않고 throw 날리면 위임해서 뒤로 위임함
컨트롤러가 throw를 날리면 ds까지 감
문제는 우리가 ds를 손을 못됨
이제 모든 에러를 다 throw를 날려서 ds에게 위임 시킬 것
그럼 ds가 위임 받아서 처리할 방법을 제공해줄 것
exceptionhandler를 만들어서 @ControllerAdvice 하나만 붙이면 ds가 처리해줌
package shop.mtcoding.blog.user;
import jakarta.servlet.http.HttpSession;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import shop.mtcoding.blog._core.util.Script;
@AllArgsConstructor
@Controller // 파일을 리턴함 -> @ResponseBody로 메세지 자체를 리턴
public class UserController {
    // fianl 변수는 반드시 초기화 되어야 함
    private final UserRepository userRepository; // null
    private final HttpSession session;
    // @AllArgsConstructor를 사용하면서 필요 없어짐
//    public UserController(UserRepository userRepository, HttpSession session) {
//        this.userRepository = userRepository;
//        this.session = session;
//    }
    // 원래는 get요청이나 예외 post요청하면 됨
    // 민감한 정보는 쿼리 스트링에 담아보낼 수 없음
    //원래는 get요청이나 예외 post요청하면 됨
    //민감한 정보는 쿼리 스트링에 담아보낼 수 없음
    @PostMapping("/login")
    public String login(UserRequest.LoginDTO requestDTO) {
        // 1. 유효성 검사
        if(requestDTO.getUsername().length() < 3) {
            return "error/400";
        }
        // 2. 모델 필요 select * from user_tb where username=? and password=?
        User user = userRepository.findByUsernameAndPassword(requestDTO); // DB에 조회할때 필요하니까 데이터를 받음
            session.setAttribute("sessionUser", user);
            return "redirect:/";
    }
    @PostMapping("/join")
    public @ResponseBody String join(UserRequest.JoinDTO requestDTO) {
        System.out.println(requestDTO);
        try{
            userRepository.save(requestDTO);
        } catch (Exception e) {
            return Script.back("아이디가 중복되었어요");
        }
        return Script.href("/loginForm"); // 메세지를 자바스크립트로 주면 302를 줄 필요 없음
    }
    @GetMapping("/joinForm") // view만 원함
    public String joinForm() {
        return "user/joinForm";
    }
    @GetMapping("/loginForm") // view만 원함
    public String loginForm() {
        return "user/loginForm";
    }
    @GetMapping("/user/updateForm")
    public String updateForm() {
        return "user/updateForm";
    }
    @GetMapping("/logout")
    public String logout() {
        // 1번 서랍에 있는 uset를 삭제해야 로그아웃이 됨
        session.invalidate(); // 서랍의 내용 삭제
        return "redirect:/";
    }
}3. exception 만드는 방법
- Ex400 이라는 클래스 만들어서 extends Runtiom Exception하면 exception 이 됨
 
- 터뜨릴때 throw new Ex400으로 터뜨리고
 
- handler에서 Ex400으로 받으면 됨
 
- 상태 코드로 클래스 만들면 됨
 
- @ControllerAdvice // 비정상적일때 처리하는 응답 에러 컨트롤러 -> view(파일)를 리턴
 
- @ResponseBody붙이면 메세지를 리턴
 
- @RestControllerAdvice
 
- @Controller -> @ResponseBody붙이면 메세지를 리턴
 
package shop.mtcoding.blog._core.handler;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import shop.mtcoding.blog._core.util.Script;
@ControllerAdvice // 비정상적일때 처리하는 응답 에러 컨트롤러 -> view(파일)를 리턴 -> @ResponseBody붙이면 됨
// @RestControllerAdvice : 응답을 직접 반환
// @Controller -> @ResponseBody붙이면 됨
public class CustomExceptionHandler {
    // 어떤 에러가 나타날때 처리할지 -> 분기해야함
    @ExceptionHandler(Exception.class)
    public @ResponseBody String error1(Exception e) {
       return Script.back(e.getMessage());
    }
}package shop.mtcoding.blog.user;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import shop.mtcoding.blog.board.BoardResponse;
import java.util.List;
@Repository // IoC에 new하는 방법
public class UserRepository {
    // DB에 접근할 수 있는 매니저 객체
    // 스프링이 만들어서 IoC에 넣어둔다.
    // DI에서 꺼내 쓰기만 하면된다.
    private EntityManager em; // 컴포지션
    // 생성자 주입 (DI 코드)
    public UserRepository(EntityManager em) {
        this.em = em;
    }
    @Transactional // db에 write 할때는 필수
    public void save(UserRequest.JoinDTO requestDTO){
        Query query = em.createNativeQuery("insert into user_tb(username, password, email, created_at) values(?,?,?, now())");
        query.setParameter(1, requestDTO.getUsername());
        query.setParameter(2, requestDTO.getPassword());
        query.setParameter(3, requestDTO.getEmail());
        query.executeUpdate();
    }
    public User findByUsernameAndPassword(UserRequest.LoginDTO requestDTO) {
        Query query = em.createNativeQuery("select * from user_tb where username=? and password=?", User.class); // 알아서 매핑해줌
        query.setParameter(1, requestDTO.getUsername());
        query.setParameter(2, requestDTO.getPassword());
        try { // 내부적으로 터지면 터지는 위치를 찾아서 내가 잡으면 됨
            User user = (User) query.getSingleResult();
            return user;
        } catch (Exception e) {
            throw new RuntimeException("아이디 혹은 비밀번호를 찾을 수 없습니다");
        }
    }
}package shop.mtcoding.blog.user;
import jakarta.servlet.http.HttpSession;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import shop.mtcoding.blog._core.util.Script;
@AllArgsConstructor
@Controller // 파일을 리턴함 -> @ResponseBody로 메세지 자체를 리턴
public class UserController {
    // fianl 변수는 반드시 초기화 되어야 함
    private final UserRepository userRepository; // null
    private final HttpSession session;
    // @AllArgsConstructor를 사용하면서 필요 없어짐
//    public UserController(UserRepository userRepository, HttpSession session) {
//        this.userRepository = userRepository;
//        this.session = session;
//    }
    // 원래는 get요청이나 예외 post요청하면 됨
    // 민감한 정보는 쿼리 스트링에 담아보낼 수 없음
    //원래는 get요청이나 예외 post요청하면 됨
    //민감한 정보는 쿼리 스트링에 담아보낼 수 없음
    @PostMapping("/login")
    public String login(UserRequest.LoginDTO requestDTO) {
        // 1. 유효성 검사
        if(requestDTO.getUsername().length() < 3) {
            return "error/400";
        }
        // 2. 모델 필요 select * from user_tb where username=? and password=?
        User user = userRepository.findByUsernameAndPassword(requestDTO); // DB에 조회할때 필요하니까 데이터를 받음
            session.setAttribute("sessionUser", user);
            return "redirect:/";
    }
    @PostMapping("/join")
    public @ResponseBody String join(UserRequest.JoinDTO requestDTO) {
        System.out.println(requestDTO);
        try{
            userRepository.save(requestDTO);
        } catch (Exception e) {
            return Script.back("아이디가 중복되었어요");
        }
        return Script.href("/loginForm"); // 메세지를 자바스크립트로 주면 302를 줄 필요 없음
    }
    @GetMapping("/joinForm") // view만 원함
    public String joinForm() {
        return "user/joinForm";
    }
    @GetMapping("/loginForm") // view만 원함
    public String loginForm() {
        return "user/loginForm";
    }
    @GetMapping("/user/updateForm")
    public String updateForm() {
        return "user/updateForm";
    }
    @GetMapping("/logout")
    public String logout() {
        // 1번 서랍에 있는 uset를 삭제해야 로그아웃이 됨
        session.invalidate(); // 서랍의 내용 삭제
        return "redirect:/";
    }
}



package shop.mtcoding.blog.user;
import jakarta.servlet.http.HttpSession;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import shop.mtcoding.blog._core.util.Script;
@AllArgsConstructor
@Controller // 파일을 리턴함 -> @ResponseBody로 메세지 자체를 리턴
public class UserController {
    // fianl 변수는 반드시 초기화 되어야 함
    private final UserRepository userRepository; // null
    private final HttpSession session;
    // @AllArgsConstructor를 사용하면서 필요 없어짐
//    public UserController(UserRepository userRepository, HttpSession session) {
//        this.userRepository = userRepository;
//        this.session = session;
//    }
    // 원래는 get요청이나 예외 post요청하면 됨
    // 민감한 정보는 쿼리 스트링에 담아보낼 수 없음
    //원래는 get요청이나 예외 post요청하면 됨
    //민감한 정보는 쿼리 스트링에 담아보낼 수 없음
    @PostMapping("/login")
    public String login(UserRequest.LoginDTO requestDTO) {
        // 1. 유효성 검사
        if(requestDTO.getUsername().length() < 3) {
            return "error/400";
        }
        // 2. 모델 필요 select * from user_tb where username=? and password=?
        User user = userRepository.findByUsernameAndPassword(requestDTO); // DB에 조회할때 필요하니까 데이터를 받음
            session.setAttribute("sessionUser", user);
            return "redirect:/";
    }
    @PostMapping("/join")
    public String join(UserRequest.JoinDTO requestDTO) {
        System.out.println(requestDTO);
        try{
            userRepository.save(requestDTO);
        } catch (Exception e) {
            throw new RuntimeException("아이디가 중복되었어요"); // 위임시키면 로직의 변화없이 오류를 위임하고 끝남
        }
        return "redirect:/loginForm";
    }
    @GetMapping("/joinForm") // view만 원함
    public String joinForm() {
        return "user/joinForm";
    }
    @GetMapping("/loginForm") // view만 원함
    public String loginForm() {
        return "user/loginForm";
    }
    @GetMapping("/user/updateForm")
    public String updateForm() {
        return "user/updateForm";
    }
    @GetMapping("/logout")
    public String logout() {
        // 1번 서랍에 있는 uset를 삭제해야 로그아웃이 됨
        session.invalidate(); // 서랍의 내용 삭제
        return "redirect:/";
    }
}


Share article