포토그램

[Chapter 3 Part 1] 포토그램 인증

yukuda 2024. 2. 22. 20:30
728x90

18. 회원가입-SecurityConfig 생성

  • 시큐리티 세팅
  • 회원가입 구현
  • 로그인 구현
  • 회원정보 수정 구현

 

우린 localhost:8080 을 쳤지만 시큐리티인 localhost:8080/login 페이지로 감(리다이렉트)

수정하고 싶음

com.cos.photogramstart.config.SecurityConfig.java

package com.cos.photogramstart.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity // 해당 파일로 시큐리티를 활성화
@Configuration // IoC
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// super 삭제 -> 기존 시큐리티가 가지고 있는 기능이 다 비활성화됨 (localhost:8080 -> localhost:8080/login 을 비활성화)
		http.authorizeRequests()
			.antMatchers("/","/user/**","/image/**","/subscribe/**","/comment/**").authenticated() // 인증이 필요
			.anyRequest().permitAll() // 그 외는 허용
			.and()
			.formLogin()
			.loginPage("/auth/signin") // 인증이 필요한 url이면 이쪽으로 자동으로 가게 하겠다
			.defaultSuccessUrl("/"); // 로그인이 정상적으로 처리되면 / 로 가게 할게
	}
}

 

19. 회원가입-CSFR 포큰 해제

com.cos.photogramstart.web.AuthController.java

package com.cos.photogramstart.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Controller // 1. IoC 2. 파일을 리턴하는 컨트롤러
public class AuthController {

	@GetMapping("/auth/signin")
	public String signinForm() {
		return "/auth/signin";
	}
	
	@GetMapping("/auth/signup")
	public String signupForm() {
		return "/auth/signup";
	}
	
	// 예상: 회원가입버튼 -> /auth/siginup -> /auth/signin
	// 결과: 회원가입버튼 -> 아무것도 안됨 (CSRF 토큰이 있기 때문) (정상적인 사용자인지 구분하기 위함)
	@PostMapping("/auth/signup") // 회원가입이 성공하면 로그인 페이지로
	public String signup() {
		
		return "/auth/signin";
	}
}

signup.jsp 추가

<!--회원가입 인풋-->
 <form class="login__input" action="/auth/signup" method="post">

SecurityConfig.java 추가

http.csrf().disable();

 

20. 회원가입-User 모델 만들기

com.cos.photogramstart.web.dte.auth.SignupDto.java

package com.cos.photogramstart.web.dte.auth;

import lombok.Data;

@Data // Getter, Setter
public class SignupDto { // 통신할때 필요한 데이터를 담아두는 오브젝트 (username,password,email,name)

	private String username;
	private String password;
	private String email;
	private String name;
}

AuthController.java 추가

@PostMapping("/auth/signup") // 회원가입이 성공하면 로그인 페이지로
	public String signup(SignupDto signupDto) { // key = value(x-www-form-urlencoded)
		log.info(signupDto.toString());
		
		return "/auth/signin";
	}

com.cos.photogramstart.domain.user.User.java

package com.cos.photogramstart.domain.user;

import java.time.LocalDateTime;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PrePersist;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

// JPA - Java Persistence API (자바로 데이터를 영구적으로 저장(DB)할 수 있는 API를 제공)

@Entity // DB에 테이블을 생성
@Data
@NoArgsConstructor // 빈 생성자
@AllArgsConstructor // 전체 생성자
public class User {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY) // 번호 증가 전략이 데이터베이스를 따라간다.
	private int id;
	
	private String username;
	private String password;
	
	private String name;
	private String website;
	private String bio; // 자기 소개
	private String email;
	private String phone;
	private String gender;
	
	private String profileImageUrl; // 작성자 사진
	private String role; // 권한
	
	private LocalDateTime createDate;
	
	@PrePersist // DB에 Insert가 되기 직전에 실행
	public void createDate() {
		this.createDate = LocalDateTime.now();
	}
}

 

21. 회원가입-완료

이제 받은 데이터를 DB에 저장하기 위해 Service 가 필요

User.java @Builder 추가

package com.cos.photogramstart.domain.user;

import java.time.LocalDateTime;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PrePersist;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

// JPA - Java Persistence API (자바로 데이터를 영구적으로 저장(DB)할 수 있는 API를 제공)

@Builder
@Entity // DB에 테이블을 생성
@Data
@NoArgsConstructor // 빈 생성자
@AllArgsConstructor // 전체 생성자
public class User {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY) // 번호 증가 전략이 데이터베이스를 따라간다.
	private int id;
	
	private String username;
	private String password;
	
	private String name;
	private String website;
	private String bio; // 자기 소개
	private String email;
	private String phone;
	private String gender;
	
	private String profileImageUrl; // 작성자 사진
	private String role; // 권한
	
	private LocalDateTime createDate;
	
	@PrePersist // DB에 Insert가 되기 직전에 실행
	public void createDate() {
		this.createDate = LocalDateTime.now();
	}
}

SignupDto.java toEntity 추가

package com.cos.photogramstart.web.dte.auth;

import com.cos.photogramstart.domain.user.User;

import lombok.Data;

@Data // Getter, Setter
public class SignupDto { // 통신할떄 필요한 데이터를 담아두는 오브젝트 (username,password,email,name)

	private String username;
	private String password;
	private String email;
	private String name;
	
	public User toEntity() {
		return User.builder()
				.username(username)
				.password(password)
				.email(email)
				.name(name)
				.build();
	}
}

com.cos.photogramstart.service.AuthService.java

package com.cos.photogramstart.service;

import org.springframework.stereotype.Service;

import com.cos.photogramstart.domain.user.User;
import com.cos.photogramstart.domain.user.UserRepository;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Service // 1. IoC 2. 트랜잭션 관리
public class AuthService {

	private final UserRepository userRepository;
	
	public User 회원가입(User user) {
		// 회원가입 진행
		User userEntity = userRepository.save(user);
		return userEntity;
	}
}

com.cos.photogramstart.domain.user.UserRepository.java

package com.cos.photogramstart.domain.user;

import org.springframework.data.jpa.repository.JpaRepository;

// 어노테이션이 없어도 JpaRepository를 상속하면 IoC 등록이 자동으로 된다.
public interface UserRepository extends JpaRepository<User, Integer>{

}

AuthController.java 추가

package com.cos.photogramstart.web;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import com.cos.photogramstart.domain.user.User;
import com.cos.photogramstart.service.AuthService;
import com.cos.photogramstart.web.dte.auth.SignupDto;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor // final이 걸려있는 모든 생성자 생성 // final 필드를 DI 할때 사용
@Controller // 1. IoC 2. 파일을 리턴하는 컨트롤러
public class AuthController {

	private static final Logger log = LoggerFactory.getLogger(AuthController.class);

	
	private final AuthService authService;
	
//	public AuthController(AuthService authService) {
//		this.authService = authService; // 의존성 주입
//	}
	
	@GetMapping("/auth/signin")
	public String signinForm() {
		return "/auth/signin";
	}
	
	@GetMapping("/auth/signup")
	public String signupForm() {
		return "/auth/signup";
	}
	
	// 예상: 회원가입버튼 -> /auth/siginup -> /auth/signin
	// 결과: 회원가입버튼 -> 아무것도 안됨 (CSRF 토큰이 있기 때문) (정상적인 사용자인지 구분하기 위함)
	@PostMapping("/auth/signup") // 회원가입이 성공하면 로그인 페이지로
	public String signup(SignupDto signupDto) { // key = value(x-www-form-urlencoded)
		log.info(signupDto.toString());
		
		// User <- SignupDto
		User user = signupDto.toEntity();
		log.info(user.toString());
		
		User userEntity = authService.회원가입(user);
		System.out.println(userEntity);
		return "/auth/signin";
	}
}

22. 회원가입-비밀번호 해시

비밀번호 암호화 + 권한 수정

AuthService.java

package com.cos.photogramstart.service;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cos.photogramstart.domain.user.User;
import com.cos.photogramstart.domain.user.UserRepository;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Service // 1. IoC 2. 트랜잭션 관리
public class AuthService {

	private final UserRepository userRepository;
	private final BCryptPasswordEncoder bCryptPasswordEncoder;
	
	@Transactional // Write(Insert, Update, Delete) 트랜잭션 관리
	public User 회원가입(User user) {
		// 회원가입 진행
		String rawPassword = user.getPassword();
		String encPassword = bCryptPasswordEncoder.encode(rawPassword); // 해시로 암호화
		user.setPassword(encPassword);
		
		user.setRole("ROLE_USER"); // 관리자 ROLE_ADMIN
		User userEntity = userRepository.save(user);
		return userEntity;
	}
}

SecurityConfig.java

package com.cos.photogramstart.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@EnableWebSecurity // 해당 파일로 시큐리티를 활성화
@Configuration // IoC
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	public BCryptPasswordEncoder encode() {
		return new BCryptPasswordEncoder();
	}
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// super 삭제 -> 기존 시큐리티가 가지고 있는 기능이 다 비활성화됨 (localhost:8080 -> localhost:8080/login 을 비활성화)
		http.csrf().disable();
		http.authorizeRequests()
			.antMatchers("/","/user/**","/image/**","/subscribe/**","/comment/**").authenticated() // 인증이 필요
			.anyRequest().permitAll() // 그 외는 허용
			.and()
			.formLogin()
			.loginPage("/auth/signin") // 인증이 필요한 url이면 이쪽으로 자동으로 가게 하겠다
			.defaultSuccessUrl("/"); // 로그인이 정상적으로 처리되면 / 로 가게 할게
	}
}

User.java username 유니크 추가

package com.cos.photogramstart.domain.user;

import java.time.LocalDateTime;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PrePersist;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

// JPA - Java Persistence API (자바로 데이터를 영구적으로 저장(DB)할 수 있는 API를 제공)

@Builder
@Entity // DB에 테이블을 생성
@Data
@NoArgsConstructor // 빈 생성자
@AllArgsConstructor // 전체 생성자
public class User {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY) // 번호 증가 전략이 데이터베이스를 따라간다.
	private int id;
	
	@Column(unique = true)
	private String username;
	private String password;
	
	private String name;
	private String website;
	private String bio; // 자기 소개
	private String email;
	private String phone;
	private String gender;
	
	private String profileImageUrl; // 작성자 사진
	private String role; // 권한
	
	private LocalDateTime createDate;
	
	@PrePersist // DB에 Insert가 되기 직전에 실행
	public void createDate() {
		this.createDate = LocalDateTime.now();
	}
}

23. 회원가입-전처리 후처리 개념잡기

AOP: 간점(회원가입) 지향 프로그래밍 (전처리, 후처리)

24. 회원가입-유효성 검사하기

pom.xml 추가

<!--
		https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
			<version>2.4.4</version>
		</dependency>

SignupDto.java 추가

package com.cos.photogramstart.web.dte.auth;

import javax.validation.constraints.Max;
import javax.validation.constraints.NotBlank;

import com.cos.photogramstart.domain.user.User;

import lombok.Data;

@Data // Getter, Setter
public class SignupDto { // 통신할떄 필요한 데이터를 담아두는 오브젝트 (username,password,email,name)
	
	@Max(20)
	private String username;
	@NotBlank
	private String password;
	@NotBlank
	private String email;
	@NotBlank
	private String name;
	
	public User toEntity() {
		return User.builder()
				.username(username)
				.password(password)
				.email(email)
				.name(name)
				.build();
	}
}

User.java 추가

package com.cos.photogramstart.domain.user;

import java.time.LocalDateTime;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PrePersist;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

// JPA - Java Persistence API (자바로 데이터를 영구적으로 저장(DB)할 수 있는 API를 제공)

@Builder
@Entity // DB에 테이블을 생성
@Data
@NoArgsConstructor // 빈 생성자
@AllArgsConstructor // 전체 생성자
public class User {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY) // 번호 증가 전략이 데이터베이스를 따라간다.
	private int id;
	
	@Column(length = 20, unique = true)
	private String username;
	
	@Column(nullable=false)
	private String password;
	
	@Column(nullable=false)
	private String name;
	
	private String website;
	private String bio; // 자기 소개
	
	@Column(nullable=false)
	private String email;
	
	private String phone;
	private String gender;
	
	private String profileImageUrl; // 작성자 사진
	private String role; // 권한
	
	private LocalDateTime createDate;
	
	@PrePersist // DB에 Insert가 되기 직전에 실행
	public void createDate() {
		this.createDate = LocalDateTime.now();
	}
}

AuthController.java 추가

package com.cos.photogramstart.web;

import java.util.HashMap;
import java.util.Map;

import javax.validation.Valid;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import com.cos.photogramstart.domain.user.User;
import com.cos.photogramstart.service.AuthService;
import com.cos.photogramstart.web.dte.auth.SignupDto;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor // final이 걸려있는 모든 생성자 생성 // final 필드를 DI 할때 사용
@Controller // 1. IoC 2. 파일을 리턴하는 컨트롤러
public class AuthController {

	private static final Logger log = LoggerFactory.getLogger(AuthController.class);

	private final AuthService authService;
	
//	public AuthController(AuthService authService) {
//		this.authService = authService; // 의존성 주입
//	}
	
	@GetMapping("/auth/signin")
	public String signinForm() {
		return "/auth/signin";
	}
	
	@GetMapping("/auth/signup")
	public String signupForm() {
		return "/auth/signup";
	}
	
	// 예상: 회원가입버튼 -> /auth/siginup -> /auth/signin
	// 결과: 회원가입버튼 -> 아무것도 안됨 (CSRF 토큰이 있기 때문) (정상적인 사용자인지 구분하기 위함)
	@PostMapping("/auth/signup") // 회원가입이 성공하면 로그인 페이지로
	public String signup(@Valid SignupDto signupDto, BindingResult bindingResult) { // key = value(x-www-form-urlencoded)
		log.info(signupDto.toString());
		
		if(bindingResult.hasErrors()) {
			Map<String, String> errorMap = new HashMap<>();
			
			for(FieldError error : bindingResult.getFieldErrors()) {
				errorMap.put(error.getField(),error.getDefaultMessage());
				System.out.println(error.getDefaultMessage());
			}
		}
		
		// User <- SignupDto
		User user = signupDto.toEntity();
		log.info(user.toString());
		
		User userEntity = authService.회원가입(user);
		System.out.println(userEntity);
		return "/auth/signin";
	}
}

25. 회원가입-@ResponseBody 사용하기

백쪽에서 막고 프론트쪽에서도 막아야 안전

요청에 대한 분기

@Controller 인데 @ResponseBody가 있으면 데이터를 반환

SignupDto.java 수정

@Size(min=2,max=20)
@NotBlank
private String username;

AuthController.java 수정

package com.cos.photogramstart.web;

import java.util.HashMap;
import java.util.Map;

import javax.validation.Valid;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cos.photogramstart.domain.user.User;
import com.cos.photogramstart.service.AuthService;
import com.cos.photogramstart.web.dte.auth.SignupDto;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor // final이 걸려있는 모든 생성자 생성 // final 필드를 DI 할때 사용
@Controller // 1. IoC 2. 파일을 리턴하는 컨트롤러
public class AuthController {

	
	private static final Logger log = LoggerFactory.getLogger(AuthController.class);

	
	private final AuthService authService;
	
//	public AuthController(AuthService authService) {
//		this.authService = authService; // 의존성 주입
//	}
	
	@GetMapping("/auth/signin")
	public String signinForm() {
		return "/auth/signin";
	}
	
	@GetMapping("/auth/signup")
	public String signupForm() {
		return "/auth/signup";
	}
	
	// 예상: 회원가입버튼 -> /auth/siginup -> /auth/signin
	// 결과: 회원가입버튼 -> 아무것도 안됨 (CSRF 토큰이 있기 때문) (정상적인 사용자인지 구분하기 위함)
	@PostMapping("/auth/signup") // 회원가입이 성공하면 로그인 페이지로
	public @ResponseBody String signup(@Valid SignupDto signupDto, BindingResult bindingResult) { // key = value(x-www-form-urlencoded)
		log.info(signupDto.toString());
		
		if(bindingResult.hasErrors()) {
			Map<String, String> errorMap = new HashMap<>();
			
			for(FieldError error : bindingResult.getFieldErrors()) {
				errorMap.put(error.getField(),error.getDefaultMessage());
				System.out.println(error.getDefaultMessage());
			}
			return "오류남"; // 오류남 메시지 출력
		}else {
			// User <- SignupDto
			User user = signupDto.toEntity();
			log.info(user.toString());
			
			User userEntity = authService.회원가입(user);
			System.out.println(userEntity);
			return "/auth/signin"; // /auth/signin 메시지 출력
		}
		

	}
}

26. 회원가입-글로벌 예외처리 하기

AuthController.java 추가

package com.cos.photogramstart.web;

import java.util.HashMap;
import java.util.Map;

import javax.validation.Valid;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cos.photogramstart.domain.user.User;
import com.cos.photogramstart.handler.ex.CustomValidationException;
import com.cos.photogramstart.service.AuthService;
import com.cos.photogramstart.web.dte.auth.SignupDto;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor // final이 걸려있는 모든 생성자 생성 // final 필드를 DI 할때 사용
@Controller // 1. IoC 2. 파일을 리턴하는 컨트롤러
public class AuthController {

	
	private static final Logger log = LoggerFactory.getLogger(AuthController.class);

	
	private final AuthService authService;
	
//	public AuthController(AuthService authService) {
//		this.authService = authService; // 의존성 주입
//	}
	
	@GetMapping("/auth/signin")
	public String signinForm() {
		return "/auth/signin";
	}
	
	@GetMapping("/auth/signup")
	public String signupForm() {
		return "/auth/signup";
	}
	
	// 예상: 회원가입버튼 -> /auth/siginup -> /auth/signin
	// 결과: 회원가입버튼 -> 아무것도 안됨 (CSRF 토큰이 있기 때문) (정상적인 사용자인지 구분하기 위함)
	@PostMapping("/auth/signup") // 회원가입이 성공하면 로그인 페이지로
	public String signup(@Valid SignupDto signupDto, BindingResult bindingResult) { // key = value(x-www-form-urlencoded)
		log.info(signupDto.toString());
		
		if(bindingResult.hasErrors()) {
			Map<String, String> errorMap = new HashMap<>();
			
			for(FieldError error : bindingResult.getFieldErrors()) {
				errorMap.put(error.getField(),error.getDefaultMessage());
				System.out.println(error.getDefaultMessage());
			}
			throw new CustomValidationException("유효성 검사 실패함", errorMap);
		}else {
			// User <- SignupDto
			User user = signupDto.toEntity();
			log.info(user.toString());
			
			User userEntity = authService.회원가입(user);
			System.out.println(userEntity);
			return "/auth/signin";
		}
		

	}
}

com.cos.photogramstart.handler.ControllerExceptionHandler.java

package com.cos.photogramstart.handler;

import java.util.Map;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import com.cos.photogramstart.handler.ex.CustomValidationException;

@RestController // 낚아챈 데이터
@ControllerAdvice // 모든 exception을 낚아챔
public class ControllerExceptionHandler {

	@ExceptionHandler(CustomValidationException.class)
	public Map<String,String> vaildationException(CustomValidationException e) {
		return e.getErrorMap();
	}
}

com.cos.photogramstart.handler.ex.CustomValidationException.java

package com.cos.photogramstart.handler.ex;

import java.util.Map;

public class CustomValidationException extends RuntimeException{
	
	// 객체를 구분할 때
	private static final long serialVersionUID = 1L;
	
	private Map<String, String> errorMap;
	
	public CustomValidationException(String message, Map<String, String> errorMap) {
		super(message);
		this.errorMap = errorMap;
	}
	
	public Map<String,String> getErrorMap() {
		return errorMap;
	}

}

27. 회원가입-공통 응답 DTO 만들기

com.cos.photogramstart.web.dto.CMRespDto.java

package com.cos.photogramstart.web.dto;

import java.util.Map;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class CMRespDto<T> {
	private int code; // 1(성공), -1(실패)
	private String message;
	private T data;
	
}

ControllerExceptionHandler.java

package com.cos.photogramstart.handler;

import java.util.Map;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import com.cos.photogramstart.handler.ex.CustomValidationException;
import com.cos.photogramstart.web.dto.CMRespDto;

@RestController // 낚아챈 데이터
@ControllerAdvice // 모든 exception을 낚아챔
public class ControllerExceptionHandler {

	@ExceptionHandler(CustomValidationException.class)
	public CMRespDto<?> vaildationException(CustomValidationException e) {
		return new CMRespDto<Map<String,String>>(-1,e.getMessage(),e.getErrorMap());
	}
}

28. 회원가입-공통 응답 Script 만들기

com.cos.photogramstart.util.Script.java

package com.cos.photogramstart.util;

public class Script {

	public static String back(String msg) {
		StringBuffer sb = new StringBuffer();
		sb.append("<script>");
		sb.append("alert('"+msg+"');"); // 경고창 뛰우고
		sb.append("history.back();"); // 뒤로 돌아감
		sb.append("</script>");
		return sb.toString();
	}
}

ControllerExceptionHandler.java

package com.cos.photogramstart.handler;

import java.util.Map;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import com.cos.photogramstart.handler.ex.CustomValidationException;
import com.cos.photogramstart.util.Script;
import com.cos.photogramstart.web.dto.CMRespDto;

@RestController // 낚아챈 데이터
@ControllerAdvice // 모든 exception을 낚아챔
public class ControllerExceptionHandler {

	@ExceptionHandler(CustomValidationException.class)
	public String vaildationException(CustomValidationException e) {
		// CMRespDto, Script 비교
		// 1.클라이언트에게 응답할때는 Script 좋음
		// 2.Ajax통신 - CMRespDto
		// 3.Android통신 - CMRespDto
		return Script.back(e.getErrorMap().toString());
		//return new CMRespDto<Map<String,String>>(-1,e.getMessage(),e.getErrorMap());
	}
}

 

확인 누르면 다시 로그인 창으로