교재
책 : 초보 웹 개발자를 위한 스프링5 프로그래밍 입문 챕터 14, 15, 16
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>in.wonj</groupId>
<artifactId>sp5-wonjin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.22</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.22</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
<version>10.0.23</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.2.Final</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.9.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<release>18</release>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
</plugin>
</plugins>
</build>
</project>
컨트롤러에서 예외가 발생 했을 때 처리할 컨트롤러를 지정할 수 있다.
@ExceptionHandler 어노테이션을 붙인 메소드가 예외를 처리한다.
...
@Controller
public class SomethingController {
@RequestMapping("/경로")
public String someMethod() {
throw new MyException();
return "정상 처리됐을 때 View 이름"
}
@ExceptionHandler(MyException.class)
public String handleMyException() {
return "예외 처리 후 보여줄 View 이름"
}
}
// ControllerConfig.java
...
@Configuration
public class ControllerConfig {
...
@Bean
public SomethingController somethingController() {
return new SomethingController();
}
@Bean
public CommonHandler commonHandler() {
return new CommonHandler();
}
}
// SomethingController.java
...
@Controller
public class SomethingController {
@RequestMapping("/경로")
public String someMethod() {
throw new MyException();
return "정상 처리됐을 때 View 이름"
}
}
// CommonHandler.java
...
@ControllerAdvice("aaa") // aaa패키지와 그 하위 패키지에 대해 적용
public class CommonHandler {
@ExceptionHandler(MyException.class)
public String handleMyException() {
return "예외 처리 후 보여줄 View 이름"
}
}
@ControllerAdvice와 사용법 동일
@RestController에 대한 예외처리에 사용
Boomerang - SOAP & REST Client
위 크롬 익스텐션으로 간편하게 요청을 날릴 수 있다.
JSON요청을 받는 컨트롤러는 @RestController어노테이션을 붙여 표시한다.
...
@RestController
public class SomethingController {
@RequestMapping
(method)
...
}
요청매핑 메소드의 커맨드객체 인수에 @RequestBody어노테이션을 붙여 JSON요청 데이터를 받을 수 있다.
요청을 넣는 클라이언트는 application/json 타입으로 컨텐츠를 보내야 한다.
...
@RestController
public class SomethingController {
@PostMapping("경로")
public String test(@RequestBody CommandObject cmd, Model model) {
model.addAttribute("data", cmd.getData());
return "JSP View이름"
}
}
...
@RestController
public class SomethingController {
@PostMapping("경로")
public String test(HttpServletResponse res) {
try {
res.setHeader("MYNAME", "WONJIN");
res.setStatus(HttpServletResponse.SC_CREATED);
} catch (Exception e) {
res.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
}
아래 두 의존을 추가하고 클래스를 반환하면 Jackson에 의해 객체를 JSON으로 변환해 응답한다.
이 때, 클래스의 필드에 @JsonIgnore를 붙이면 응답JSON에서 제외한다.
아래 코드는 txt필드를 포함하고 chk는 제외한 JSON을 전송한다.
...
@RestController
public class SomethingController {
@PostMapping("test")
public TestCmd sendJson(@RequestBody TestCmd testCmd) {
return testCmd;
}
}
// TestCmd.java
package test;
import javax.validation.constraints.AssertTrue;
import org.hibernate.validator.constraints.NotBlank;
public class TestCmd {
private String txt;
@JsonIgnore
private Boolean chk;
// setter getter 생략
}
List<Object>를 리턴하면 json객체의 배열로 응답한다.
...
@RestController
public class SomethingController {
@PostMapping("test")
public List<Something> sendJson() {
List<Something> list = /* initializing, add, .. */
return list;
}
}
JSON으로 변환할 클래스를 ResponseEntity의 body에 담아 전송할 수도 있다.
정상 응답과 에러응답 모두 일관되게 JSON응답으로 처리할 수 있다.
에러 응답은 아래 코드처럼 하드코딩 하지 않고, 공통 응답으로 분리할 수 있다.
@ExceptionHandler로 에러 응답을 할 수 있다.@RestControllerAdvice로 별도 클래스로 분리할 수 있다....
class ErrRes {
private String msg;
public String getMsg() { return msg; }
public void setMsg(String msg) { this.msg = msg; }
}
@RestController
public class SomethingController {
@PostMapping("test")
public ResponseEntity<Object> sendJson(@RequestBody TestCmd testCmd) {
try {
return ResponseEntity.status(HttpStatus.OK)
.body(testCmd);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ErrRes("아무것도없잖아"));
}
}
}
body가 없는 경우 .body() 대신 .build()로 문장을 끝내거나 특정 상태 메소드를 사용한다.
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/ResponseEntity.html
...
@RestController
public class SomethingController {
@PostMapping("test")
public ResponseEntity<Object> sendJson(@RequestBody TestCmd testCmd) {
try {
return ResponseEntity.status(HttpStatus.OK).build();
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
}
@PostMapping("test_2")
public ResponseEntity<Object> sendJson(@RequestBody TestCmd testCmd) {
try {
return ResponseEntity.ok() // 200
} catch (Exception e) {
return ResponseEntity.noContent(); // 204
return ResponseEntity.badRequest(); // 400
return ResponseENTITY.notFound(); // 404
}
}
}