接着Spring 5.2.2 MVC (2)基于DispatcherServlet
的内容继续讲。java
异常状况
web
若是在请求映射期间发生异常或请求处理程序(如@Controller)引起异常,DispatcherServlet将委托给HandlerExceptionResolver bean chain(链) 以解决异常并提供替代处理,这种典型的错误响应。typescript
下表列出了可用的HandlerExceptionResolver 实现:浏览器
1)chain(链) 解析器
微信
经过在Spring配置中声明多个HandlerExceptionResolver
bean并根据须要设置它们的order
属性,能够造成异常解析器链。order
属性越大,异常解决程序的位置就越晚。app
HandlerExceptionResolver
指定它能够返回:ui
指向错误视图的
ModelAndView
。spa若是异常是在解析器中处理的,则为空的
ModelAndView
。.net若是异常仍然未解决,则为空,以便后续的解析器尝试,若是异常仍然保留在最后,则容许冒泡上升到Servlet容器。3d
MVC配置会自动声明为默认Spring MVC异常、@ResponseStatus注解的异常以及@ExceptionHandler方法的支持声明内置的解析器。能够自定义或替换该列表。
2)容器错误页
若是任何HandlerExceptionResolver仍然没法解决异常,那么该异常将被保留以传播,或者若是响应状态设置为错误状态(即4xx、5xx),则Servlet容器能够在HTML中呈现默认的错误页。要自定义容器的默认错误页,能够在web.xml中声明错误页映射。下面的示例演示了如何执行此操做:
<error-page> <location>/error</location></error-page>
在前面的示例中,当出现异常或响应具备错误状态时,Servlet容器在容器内对配置的URL进行错误分派(例如/error
)。而后由DispatcherServlet
进行处理,可能将其映射到@Controller
,后者能够实现返回带有model 的错误视图名称或返回JSON响应,以下例所示:
public class ErrorController {
"/error") (path = public Map<String, Object> handle(HttpServletRequest request) { Map<String, Object> map = new HashMap<String, Object>(); map.put("status", request.getAttribute("javax.servlet.error.status_code")); map.put("reason", request.getAttribute("javax.servlet.error.message")); return map; }}
Servlet API没有提供在Java中建立错误页映射的方法。可是你能够同时使用WebApplicationInitializer
和最少的web.xml
。
view解析
Spring MVC定义了ViewResolver
和View
接口,这些接口容许你在浏览器中渲染模型,而没必要绑定到特定的视图技术。ViewResolver
提供视图名称和实际视图之间的映射。View
访问地址在移交给特定视图技术以前的数据准备。
下表提供了有关ViewResolver
层次结构的详细信息(ViewResolver
实现):
1)处理(Handling)
能够经过声明多个解析器bean来连接视图解析器,若是须要,还能够经过设置order
属性来指定顺序。记住,order
属性值越大,视图解析器在链中的位置就越晚。
ViewResolver
的规范指定它能够返回null
以指明找不到视图。可是,对于JSP和InternalResourceViewResolver,判断JSP是否存在的惟一方法是经过RequestDispatcher执行分派。因此必须将InternalResourceViewResolver
配置为视图解析器的总顺序中的最后一个。
配置视图解析和将ViewResolver
bean添加到Spring配置同样简单。MVC配置为视图解析器和添加无逻辑视图控制器提供了一个专用的配置API,这对于没有控制器逻辑的HTML模板呈现很是有用。
2)重定向(Redirecting)
视图名称中的特殊redirect:前缀容许你执行重定向。UrlBasedViewResolver
(及其子类)将此识别为须要重定向的指令。视图名称的其他部分是重定向URL。
实际效果与控制器返回RedirectView相同,但如今控制器自己能够根据逻辑视图名称进行操做。逻辑视图名称(例如redirect:/myapp/some/resource)相对于当前的Servlet上下文重定向,而redirect:https://myhost.com/some/arbitrary/path等名称重定向到绝对URL。
注意,若是用@ResponseStatus注解了控制器方法,则注解值优先于RedirectView设置的响应状态。
3)转发(Forwarding)
你还能够由UrlBasedViewResolver
和子类解析的视图名称使用特殊的forward:前缀。这将建立一个InternalResourceView,它执行RequestDispatcher.forward()。所以这个前缀对于InternalResourceViewResolver
和InternalResourceView
(对于JSP)是没有用的,可是若是你使用另外一种视图技术,但仍然但愿强制资源的转发由Servlet/JSP引擎处理,那么它可能会有帮助。请注意,你也能够连接多个视图解析器。
4)内容规范(Content Negotiation)
ContentNegotiatingViewResolver
不解析视图自己,而是将其委托给其余视图解析器,并选择与客户端请求的表示相似的视图。能够经过Accept
头或查询参数(例如"/path?format=pdf")。
ContentNegotiatingViewResolver经过将请求媒体类型与每一个ViewResolver关联的View
所支持的媒体类型(也称为Content-Type)进行比较,选择适当的View
来处理请求。列表中具备兼容Content-Type的第一个View
表示返回给客户端。若是ViewResolver链没法提供兼容视图,则会查找经过DefaultViews
属性指定的Views
列表。后一个选项适用于能够呈现当前资源的适当表示的单例视图,而无论逻辑视图名称如何。Accept头能够包含通配符(例如text/*),在这种状况下,Content-Type为text/xml的视图是兼容的匹配项。
明天把基于DispatcherServlet
的剩余内容讲完。
敬请持续关注。
欢迎关注和转发Spring中文社区(加微信群,能够关注后加我微信):
本文分享自微信公众号 - Spring中文社区(gh_81d233bb13a4)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。