(1)在Web程序中,注意到使用Filter的时候,Filter由Servlet容器管理,它在Spring MVC的Web应用程序中作用范围如下:

上图中虚线框就是Filter2的拦截范围,Filter组件实际上并不知道后续内部处理是通过Spring MVC提供的DispatcherServlet还是其他Servlet组件,因为Filter是Servlet规范定义的标准组件,它可以应用于任何基于Servlet的程序中。
(2)如果只基于Spring MVC开发应用程序,还可以使用Spring MVC提供的一种功能类似Filter的拦截器:Interceptor。和Filter相比,Interceptor拦截范围不是后续整个处理流程,而是仅针对Controller拦截:

上述虚线就是Interceptor的拦截范围,所以Interceptor的拦截范围其实就是Controller方法,它实际上就相当于基于AOP的方法拦截。所以要注意,返回MoodelAndView并且渲染后,后续处理就脱离了Interceptor的拦截范围。使用Interceptor的好吃是Interceptor本身就是Spring管理的Bean,因此注入任意Bean都非常简单。此外,可以应用多个Interceptor,并且通过简单的@Order指定顺序。
(3)一个Interceptor必须实现HandlerInterceptor接口,可以选择实现preHandler()、postHandle()、afterCompletion()方法。preHandle是Controller方法调用前执行,postHandle()是Controller方法正常返回执行,而afterCompletion()是无论Controller方法是否抛出异常都会执行,参数Exception ex 就是Controller方法抛出的异常(未抛出异常是null)。
(4)在preHandle()中,也可以直接处理响应,然后返回false表示无需调用Controller方法继续处理了,通常在认证或者安全检查失败时直接返回错误响应。在postHandle()中,因为捕获了Controller方法返回的ModelAndView,所以可以继续往ModelAndView里面添加一些通用数据,很多页面需要的全局数据如Copyright信息等都可以放到这里,无需在每个Controller中重复添加。
(1)在Controller中,Spring MVC还允许定义基于@ExceptionHandler注解的异常处理方法。

异常处理方法没有固定的方法签名,可以传入Exception、HttpServletRequest等,返回可以是void,也可以是ModelAndView,上述代码通过@ExceptionHandler(RuntimeException.class)表示当发生RuntimeException的时候,就自动调用此方法处理。
(2)注意我们返回了一个新的ModelAndView,这样在应用程序内部如果发生了预料之外的异常,可以给用户显示一个出错页面,而不是简单的500 Internal Server Error或者404 Not Found。
(3)可以编写多个错误处理方法,每个方法针对特定的异常。例如,处理LoginException是的页面可以自动跳转到登录页。使用ExceptionHandler时,要注意它仅作用于当前的Controller,即ControllerA中定义的一个ExceptionHandle方法对ControllerB不起作用。
(1)在开发REST应用时,很多时候是通过页面的JavaScript和后端的REST API交互。在JavaScrept与REST交互的时候,有很多安全限制。默认情况下,浏览器按同源策略放行JavaScript调用API,即:
如果A站在域名a.com的页面的JavaScript调用A站自己的API时,没有问题;
如果A站在域名a.com页面的JavaScript调用B站b.com的API时,将被浏览器拒绝访问,因为不满足同源策略。
(2)同源要求域名要完全相同(a.com和www.a.com不同),协议要相同(http和https不同),端口要相同。要想在a.com页面的JavaScript调用b.com的API,需要使用CORS,全称Cross-Origin Resource Sharing,是HTML5规范定义的如何跨域访问资源。如果A站的JavaScript访问B站的API的时候,B站能够返回响应头Access-Control-Allow-Origin:http://a.com,那么浏览器就允许A站的JavaScript访问B站的API。
(3)注意到跨域访问能否成功,取决于B站是否愿意给A站返回一个正确地Access-Control-Allow-Origin响应头,所以决定权永远在提供API的服务方手中。使用Sping的@RestController开发REST应用时,同样会面对跨域问题。如果我们y7unxu指定的网站通过JavaScript访问这些REST API,就必须正确地设置CORS。
(1)方法一是使用@CrossOrigin注解,可以再@RestController的class级别或者方法级别定义一个@CrossOrigin,例如:

上述定义在ApiController处的@CrossOrigin注解指定了只允许来自local.liaoxuefeng.com跨域访问,允许多个于访问需要写成数组形式,例如origins = {“http://a.com”, “https://www.b.com”})。如果要允许任何域访问,写成origins = "*"即可。如果有多个REST Controller都需要使用CORS,那么,每个Controller都必须标注@CrossOrigin注解。
(2)第二种方法是在WebMvcConfigurer中定义一个全局CORS配置,下面是一个示例:

这种方式可以创建一个去哪聚CORS配置,如果仔细地设计URL结构,那么可以一目了然地看到各个URL的CORS规则,推荐使用这种方式配置CORS。