No matter what happens, good or bad, the outcome of a servlet request is a servlet response. If an exception occurs during request processing, the outcome is still a servlet response. Somehow, the exception must be translated into a response.

Spring offers a handful of ways to translate exceptions to responses:
 Certain Spring exceptions are automatically mapped to specific HTTP status codes.
 An exception can be annotated with @ResponseStatus to map it to an HTTP status code.
 A method can be annotated with @ExceptionHandler to handle the exception.

一、利用HTTP status codes的便利性

1.让Spring自动匹配Spring的自定义异常

The exceptions in table 7.1 are usually thrown by Spring itself as the result of something going wrong in DispatcherServlet or while performing validation. For example, if DispatcherServlet can’t find a controller method suitable to handle a request,a NoSuchRequestHandlingMethodException will be thrown, resulting in a response
with a status code of 404 (Not Found).

2.自己来匹配

(1)假设consider the following request-handling method from SpittleController that could result in an HTTP 404 status (but doesn’t):

   @RequestMapping(value="/{spittleId}", method=RequestMethod.GET)
public String spittle(
@PathVariable("spittleId") long spittleId,
Model model) {
Spittle spittle = spittleRepository.findOne(spittleId);
if (spittle == null) {
throw new SpittleNotFoundException();
}
model.addAttribute(spittle);
return "spittle";
}

if findOne() returns null , then a SpittleNotFoundException is thrown. For now, SpittleNotFoundException is a simple unchecked exception that looks like this:

package spittr.web;

public class SpittleNotFoundException extends RuntimeException {}

If the spittle() method is called on to handle a request, and the given ID comes up empty, the SpittleNotFoundException will (by default) result in a response with a 500 (Internal Server Error) status code. In fact, in the event of any exception that isn’t otherwise mapped, the response will always have a 500 status code. But you can change that by mapping SpittleNotFoundException otherwise.
When SpittleNotFoundException is thrown, it’s a situation where a requested resource isn’t found. The HTTP status code of 404 is precisely the appropriate response status code when a resource isn’t found. So, let’s use @ResponseStatus to
map SpittleNotFoundException to HTTP status code 404.

 package spittr.web;

 import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Spittle Not Found")
public class SpittleNotFoundException extends RuntimeException { }

After introducing this @ResponseStatus annotation, if a SpittleNotFoundException were to be thrown from a controller method, the response would have a status code of 404 and a reason of Spittle Not Found.

运行结果:

二、在controller级别处理异常@ExceptionHandler

1.自定义异常

package spittr.web;

public class DuplicateSpittleException extends RuntimeException {

}

2.抛出异常

suppose that SpittleRepository ’s save() method throws a DuplicateSpittleException if a user attempts to create a Spittle with text identical to one they’ve already created. That means the saveSpittle() method of SpittleController might need to deal with that exception. As shown in the following listing,saveSpittle() could directly handle the exception.

 @RequestMapping(method = RequestMethod.POST)
public String saveSpittle(SpittleForm form, Model model) {
try {
spittleRepository.save(
new Spittle(null, form.getMessage(), new Date(),
form.getLongitude(), form.getLatitude()));
return "redirect:/spittles";
} catch (DuplicateSpittleException e) {
return "error/duplicate";
}
}

It works fine, but the method is a bit complex. Two paths can be taken, each with a different outcome. It’d be simpler if saveSpittle() could focus on the happy path and let some other method deal with the exception.First, let’s rip the exception-handling code out of saveSpittle() :很怀疑这里是不是会自己抛出异常DuplicateSpittleException,当保存的id重复时????

 @RequestMapping(method = RequestMethod.POST)
public String saveSpittle(SpittleForm form, Model model) {
spittleRepository.save(
new Spittle(null, form.getMessage(), new Date(),
form.getLongitude(), form.getLatitude()));
return "redirect:/spittles";
}

Now let’s add a new method to SpittleController that will handle the case where DuplicateSpittleException is thrown:

@ExceptionHandler(DuplicateSpittleException.class)
public String handleDuplicateSpittle() {
return "error/duplicate";
}

If @ExceptionHandler methods can handle exceptions thrown from any handler method in the same controller class, you might be wondering if there’s a way they can handle exceptions thrown from handler methods in any controller. As of Spring 3.2 they certainly can, but only if they’re defined in a controller advice class.

三、在application级别处理异常@ControllerAdvice

A controller advice is
any class that’s annotated with @ControllerAdvice and has one or more of the following kinds of methods:
 @ExceptionHandler -annotated
 @InitBinder -annotated
 @ModelAttribute -annotated
Those methods in an @ControllerAdvice -annotated class are applied globally across all @RequestMapping -annotated methods on all controllers in an application.
The @ControllerAdvice annotation is itself annotated with @Component . Therefore,an @ControllerAdvice -annotated class will be picked up by component-scanning, just like an @Controller -annotated class.

处理应用中所有异常

 package spittr.web;

 import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; @ControllerAdvice
public class AppWideExceptionHandler { @ExceptionHandler(DuplicateSpittleException.class)
public String handleNotFound() {
return "error/duplicate";
} }

SPRING IN ACTION 第4版笔记-第七章Advanced Spring MVC-005- 异常处理@ResponseStatus、@ExceptionHandler、@ControllerAdvice的更多相关文章

  1. SPRING IN ACTION 第4版笔记-第七章Advanced Spring MVC-003- 上传文件multipart,配置StandardServletMultipartResolver、CommonsMultipartResolver

    一.什么是multipart The Spittr application calls for file uploads in two places. When a new user register ...

  2. SPRING IN ACTION 第4版笔记-第七章Advanced Spring MVC-002- 在xml中引用Java配置文件,声明DispatcherServlet、ContextLoaderListener

    一.所有声明都用xml 1. <?xml version="1.0" encoding="UTF-8"?> <web-app version= ...

  3. SPRING IN ACTION 第4版笔记-第七章Advanced Spring MVC-006- 如何保持重定向的request数据(用model、占位符、RedirectAttributes、model.addFlashAttribute("spitter", spitter);)

    一.redirect为什么会丢数据? when a handler method completes, any model data specified in the method is copied ...

  4. SPRING IN ACTION 第4版笔记-第七章Advanced Spring MVC-004- 处理上传文件

    一.用 MultipartFile 1.在html中设置<form enctype="multipart/form-data">及<input type=&quo ...

  5. SPRING IN ACTION 第4版笔记-第七章Advanced Spring MVC-001- DispatcherServlet的高级配置(ServletRegistration.Dynamic、WebApplicationInitializer)

    一. 1.如想在DispatcherServlet在Servlet容器中注册后自定义一些操作,如开启文件上传功能,则可重写通过AbstractAnnotationConfigDispatcherSer ...

  6. SPRING IN ACTION 第4版笔记-第五章Building Spring web applications-001-SpringMVC介绍

    一. 二.用Java文件配置web application 1. package spittr.config; import org.springframework.web.servlet.suppo ...

  7. SPRING IN ACTION 第4版笔记-第五章BUILDING SPRING WEB APPLICATIONS-004-以query parameters的形式给action传参数(@RequestParam、defaultValue)

    一. 1.Spring MVC provides several ways that a client can pass data into a controller’s handler method ...

  8. SPRING IN ACTION 第4版笔记-第五章BUILDING SPRING WEB APPLICATIONS-007-表单验证@Valid、Error

    一. Starting with Spring 3.0, Spring supports the Java Validation API in Spring MVC . No extra config ...

  9. SPRING IN ACTION 第4版笔记-第五章BUILDING SPRING WEB APPLICATIONS-005-以path parameters的形式给action传参数(value=“{}”、@PathVariable)

    一 1.以path parameters的形式给action传参数 @Test public void testSpittle() throws Exception { Spittle expecte ...

随机推荐

  1. Android——简单音乐播放器

    使用MediaPlayer做的简单音乐播放器,更多内容请到百度经验查看   http://jingyan.baidu.com/article/60ccbceb63452364cab197f1.html ...

  2. Android之Http网络编程(二)

    上一篇文章简单的介绍了Android中http的两种通信方式,并且分别用获取百度网页做了实例.但是在实际应用中,更多的是客户端通过请求的参数来实现在服务端的具体操作,并最终返回数据给客户端.因为我们不 ...

  3. 命令行创建Android应用,生成签名,对APK包签名并编译运行

    一.命令行创建Android应用 android create project -n HelloWorld -t android-22 -p HelloWorld1 -k org.crazyit.he ...

  4. serialize

    Jquery的serialize()方法用于将表单元素转换为查询字符串格式, Submit按钮及File选择元素是不能序列化的. $('input:button').click(function() ...

  5. 在centos7中限制kvm虚拟机可访问的资源

    最近通过艰苦卓绝的度娘(我很想用谷歌,可是,你懂的),终于搞明白如何在centos7中限制kvm虚拟机可访问的资源了.度娘给出的结果中,大部分都说的很对,然而,却很难照着做,主要原因有两点:1.网上的 ...

  6. JavaScript 学习笔记: 扩充类型的功能

    JavaScript 是允许给基本类型扩充功能的.例如,可以通过对Object.prototype增加方法,可以让该方法对所有的对象都可用. 这样的方式对函数,数组,字符串,数字,正则表达式和布尔值同 ...

  7. html元素类型 块级元素、内联元素(又叫行内元素)和内联块级元素。

    html中的标签元素大体被分为三种不同的类型:块级元素.内联元素(又叫行内元素)和内联块级元素. 块级元素特点: 1.每个块级元素都从新的一行开始,并且其后的元素也另起一行.(霸道,一个块级元素独占一 ...

  8. 学习C++ Primer 的个人理解(七)

    类,后面还有两章是介绍有关于类的内容的.这一张依然只是个概括.但也已经将大致用法介绍完了. 重点如下: 1.成员函数的声明,必须在类的内部. 2.引用const成员函数 我们知道成员函数中有一个名为t ...

  9. OpenJudge/Poj 2001 Shortest Prefixes

    1.链接地址: http://bailian.openjudge.cn/practice/2001 http://poj.org/problem?id=2001 2.题目: Shortest Pref ...

  10. OpenJudge/Poj 1005 I Think I Need a Houseboat

    1.链接地址: http://bailian.openjudge.cn/practice/1005/ http://poj.org/problem?id=1005 2.题目: I Think I Ne ...