Edited at

Springで例外ハンドリング

More than 3 years have passed since last update.


環境

Spring-Boot 1.3.3

Spring-WebMVC 4.2.5


例外ハンドリング

Springでは、Controller個別で例外をハンドリングする方法と、Controllerを横断して例外をハンドリングする方法の2通りのハンドリング方法が存在する。ここでは、RestControllerでのハンドリングを例にしてやってみる。


Controller個別で例外をハンドリングする

Controller個別で例外をハンドリングする場合、Controllerクラス内にハンドリング用のメソッドを作成する。このメソッドには@ExceptionHandlerアノテーションを付与する。そうすることでそのControllerクラス内で発生した例外に対する設定を行うことができる。


CustomerRestController.java

@RestController

@RequestMapping("api/customers")
public class CustomerRestController {

@Autowired
CustomerService customerService;

@RequestMapping(method = RequestMethod.GET)
Page<Customer> getCustomers(@PageableDefault Pageable pageable) {
Page<Customer> customers = customerService.findAll(pageable);
return customers;
}

@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@ExceptionHandler({ HttpRequestMethodNotSupportedException.class })
@ResponseBody
public Map<String, Object> handleError() {
Map<String, Object> errorMap = new HashMap<String, Object>();
errorMap.put("message", "許可されていないメソッド");
errorMap.put("status", HttpStatus.METHOD_NOT_ALLOWED);
return errorMap;
}
}




  • @ExceptionHandler({ HttpRequestMethodNotSupportedException.class })


    • このController内でHttpRequestMethodNotSupportedExceptionが発生した場合は、handleErrorメソッドでハンドリングを行う。




  • @ResponseStatus(HttpStatus.BAD_REQUEST)


    • クライアントにレスポンスを返す際のステータスコード。ここでは400を返す設定。




  • @ResponseBody


    • レスポンスにJSONを返却する際に利用するアノテーション。




Controllerを横断して例外をハンドリングする

Controllerを横断して例外をハンドリングする場合、まずは例外ハンドリング用のクラスを作成する。このクラスには@ControllerAdviceアノテーションを付与する。そうすることで全てのControllerクラスで発生した例外に対する共通の設定を行うことができる。

例えば以下の例では、TrendRestControllerとCustomerRestControllerでHttpRequestMethodNotSupportedExceptionが発生した場合、ExceptionHandlerクラスのhandleErrorメソッドで例外がハンドリングされる。


TrendRestController.java

@RestController

@RequestMapping("api/trends")
public class TrendRestController {

@RequestMapping(method = RequestMethod.GET)
String getTrends() {
return "Something Trends";
}
}



CustomerRestController.java

@RestController

@RequestMapping("api/customers")
public class CustomerRestController {

@Autowired
CustomerService customerService;

@RequestMapping(method = RequestMethod.GET)
Page<Customer> getCustomers(@PageableDefault Pageable pageable) {
Page<Customer> customers = customerService.findAll(pageable);
return customers;
}
}



ExceptionHandler.java

@ControllerAdvice

public class ExceptionHandler {

@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@org.springframework.web.bind.annotation.ExceptionHandler({ HttpRequestMethodNotSupportedException.class })
@ResponseBody
public Map<String, Object> handleError() {
Map<String, Object> errorMap = new HashMap<String, Object>();
errorMap.put("message", "許可されていないメソッド");
errorMap.put("status", HttpStatus.METHOD_NOT_ALLOWED);
return errorMap;
}
}



その他

Controllerを横断して例外をハンドリングする場合の例外ハンドリング用のクラスと、Controller個別で例外をハンドリングする場合のControllerクラスの双方で同じハンドリング処理があった場合、Controller個別で例外をハンドリングをする方が優先される。


参考

http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-error-handling

http://m12i.hatenablog.com/entry/2014/10/29/010801