1. 新建异常信息实体类
src/main/java/com/twuc/webApp/exception/ErrorResponse.java
public class ErrorResponse {
private String message;
private String errorTypeName;
public ErrorResponse(Exception e) {
this(e.getClass().getName(), e.getMessage());
}
public ErrorResponse(String errorTypeName, String message) {
this.errorTypeName = errorTypeName;
this.message = message;
}
......省略getter/setter方法
}
2. 自定义异常类型
src/main/java/com/twuc/webApp/exception/ResourceNotFoundException.java
public class ResourceNotFoundException extends RuntimeException {
private String message;
public ResourceNotFoundException() {
super();
}
public ResourceNotFoundException(String message) {
super(message);
this.message = message;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
3. 新建异常处理类
我们只需要在类上加上@ControllerAdvice
注解这个类就成为了全局异常处理类。当然你也可以通过 assignableTypes
指定特定的 Controller 类,让异常处理类只处理特定类抛出的异常。
src/main/java/com/twuc/webApp/exception/GlobalExceptionHandler.java
@ControllerAdvice(assignableTypes = {ExceptionController.class})
@ResponseBody
public class GlobalExceptionHandler {
ErrorResponse illegalArgumentResponse = new ErrorResponse(new IllegalArgumentException("参数错误!"));
ErrorResponse resourseNotFoundResponse = new ErrorResponse(new ResourceNotFoundException("Sorry, the resourse not found!"));
@ExceptionHandler(value = Exception.class)// 拦截所有异常, 这里只是为了演示,一般情况下一个方法特定处理一种异常
public ResponseEntity exceptionHandler(Exception e) {
if (e instanceof IllegalArgumentException) {
return ResponseEntity.status(400).body(illegalArgumentResponse);
} else if (e instanceof ResourceNotFoundException) {
return ResponseEntity.status(404).body(resourseNotFoundResponse);
}
return null;
}
}
4. controller模拟抛出异常
src/main/java/com/twuc/webApp/web/ExceptionController.java
@RestController
@RequestMapping("/api")
public class ExceptionController {
@GetMapping("/illegalArgumentException")
public void throwException() {
throw new IllegalArgumentException();
}
@GetMapping("/resourceNotFoundException")
public void throwException2() {
throw new ResourceNotFoundException();
}
}
5. 编写测试类
MockMvc 由org.springframework.boot.test
包提供,实现了对Http请求的模拟,一般用于我们测试 controller 层。
@AutoConfigureMockMvc
@SpringBootTest
public class ExceptionTest {
@Autowired
MockMvc mockMvc;
@Test
void should_return_400_if_param_not_valid() throws Exception {
mockMvc.perform(get("/api/illegalArgumentException"))
.andExpect(status().is(400))
.andExpect(jsonPath("$.message").value("参数错误!"));
}
@Test
void should_return_404_if_resourse_not_found() throws Exception {
mockMvc.perform(get("/api/resourceNotFoundException"))
.andExpect(status().is(404))
.andExpect(jsonPath("$.message").value("Sorry, the resourse not found!"));
}
}
我们刚刚也说了使用@ControllerAdvice
注解 可以通过 assignableTypes
指定特定的类,让异常处理类只处理特定类抛出的异常。所以这种处理异常的方式,实际上现在使用的比较少了。
我们把下面这段代码移到 src/main/java/com/twuc/webApp/exception/GlobalExceptionHandler.java
中就可以了。
@ExceptionHandler(value = Exception.class)// 拦截所有异常
public ResponseEntity exceptionHandler(Exception e) {
if (e instanceof IllegalArgumentException) {
return ResponseEntity.status(400).body(illegalArgumentResponse);
} else if (e instanceof ResourceNotFoundException) {
return ResponseEntity.status(404).body(resourseNotFoundResponse);
}
return null;
}