查看更多宝典,请点击《金三银四,你的专属面试宝典》css
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑汇集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不须要从新编写业务逻辑。html
最简单的、最经典就是Jsp(view) +Servlet(controller) + JavaBean(model)。前端
mvc框架是为了解决传统MVC模式(Jsp +Servlet + JavaBean)的一些问题而出现的框架。java
传统MVC模式问题:web
一、全部的Servlet和Servlet映射都要配置在web.xml中,若是项目太大,web.xml就太庞大,而且不能实现模块化管理。面试
二、Servlet的主要功能就是接受参数、调用逻辑、跳转页面,好比像其余字符编码、文件上传等功能也要写在Servlet中,不能让Servlet主要功能而须要作处理一下特例。ajax
三、接受参数比较麻烦(String name = request.getParameter(“name”),User user=new User user.setName(name)),不能经过model接收,只能单个接收,接收完成后转换封装model。spring
四、跳转页面方式比较单一(forword,redirect),而且当个人页面名称发生改变时须要修改Servlet源代码。数据库
前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并把请求分发到不一样的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端。前端控制器既可使用Filter实现(Struts2采用这种方式),也可使用Servlet来实现(spring MVC框架)。后端
spring MVC中的前段控制器就是DsipatcherServlet,在web.xml中配置好DispatcherServlet后,容器启动时会去WEB-INF文件夹下去找(默认[servlet-name]-servlet.xml)dispatcherServlet-servlet.xml,解析文件初始化里面中的bean等,DispatcherServlet继承自抽象类:FrameworkServlet,间接继承了HttpServlet (FrameworkServlet继承自HttpServletBean,而HttpServletBean继承自HttpServlet )。
在使用springmvc时,前端控制器会默认加载一些组件,具体配置在springwebmvc下DispatcherServlet.properties中
从如上配置能够看出DispatcherServlet在启动时会自动注册这些特殊的Bean,无需咱们注册,若是咱们注册了,默认的将不会注册。 所以BeanNameUrlHandlerMapping、SimpleControllerHandlerAdapter是不须要注册的,DispatcherServlet默认会注册这两个Bean。
Controller:处理器/页面控制器,作的是MVC中的C的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理;
HandlerMapping:请求处处理器的映射,若是映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象;如BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的Bean就是此处的处理器;
HandlerAdapter:HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器模式的应用,从而很容易支持不少类型的处理器;如SimpleControllerHandlerAdapter将对实现了Controller接口的Bean进行适配,而且调处理器的handleRequest方法进行功能处理;
ViewResolver:ViewResolver将把逻辑视图名解析为具体的View,经过这种策略模式,很容易更换其余视图技术;如InternalResourceViewResolver将逻辑视图名映射为jsp视图;
LocalResover:本地化解析,由于Spring支持国际化,所以LocalResover解析客户端的Locale信息从而方便进行国际化;
ThemeResovler:主题解析,经过它来实现一个页面多套风格,即常见的相似于如软件皮肤效果;
MultipartResolver:文件上传解析,用于支持文件上传;
HandlerExceptionResolver:处理器异常解析,能够将异常映射到相应的统一错误界面,从而显示用户友好的界面(而不是给用户看到具体的错误信息);
RequestToViewNameTranslator:当处理器没有返回逻辑视图名等相关信息时,自动将请求URL映射为逻辑视图名;
FlashMapManager:用于管理FlashMap的策略接口,FlashMap用于存储一个请求的输出,当进入另外一个请求时做为该请求的输入,一般用于重定向场景。
概述一:
一、 用户发送请求至前端控制器DispatcherServlet。
二、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
三、 处理器映射器找到具体的处理器(能够根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(若是有则生成)一并返回给DispatcherServlet。
四、 DispatcherServlet调用HandlerAdapter处理器适配器。
五、 HandlerAdapter通过适配调用具体的处理器(Controller,也叫后端控制器)。
六、 Controller执行完成返回ModelAndView。
七、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
八、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
九、 ViewReslover解析后返回具体View。
十、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
十一、 DispatcherServlet响应用户。
概述二:
一、 用户向服务器发送请求,请求被Spring前端控制器DispatcherServlet捕获(捕获)
二、 DispatcherServlet对请求URL进行解析,获得请求资源标识符(URI)。而后根据该URI,调用HandlerMapping得到该Handler配置的全部相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;(查找handler)
三、 DispatcherServlet 根据得到的Handler,选择一个合适的HandlerAdapter。 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller), Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象(执行handler)
四、DispatcherServlet 根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver) (选择ViewResolver)
五、经过ViewResolver 结合Model和View,来渲染视图,DispatcherServlet 将渲染结果返回给客户端。(渲染返回)
一、客户端浏览器发送请求
二、这个请求通过一系列的过滤器(Filter)(这些过滤器中有一个叫作ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其余框架的集成颇有帮助,例如:SiteMesh Plugin);
三、接着FilterDispatcher(StrutsPrepareAndExecuteFilter)被调用,FilterDispatcher
(StrutsPrepareAndExecuteFilter)询问ActionMapper来决定这个请求是否须要调用某个Action;
四、若是ActionMapper决定须要调用某个Action,FilterDispatcher
(StrutsPrepareAndExecuteFilter)把请求的处理交给ActionProxy;
五、ActionProxy经过Configuration Manager询问框架的配置文件,找到须要调用的Action类;
六、ActionProxy建立一个ActionInvocation的实例。
七、ActionInvocation实例使用命名模式来调用,在调用Action的过程先后,涉及到相关拦截器(Intercepter)的调用。
八、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果一般是(但不老是,也多是另外的一个Action链)一个须要被表示的JSP或者FreeMarker的模版。在表示的过程当中可使用Struts2框架中继承的标签。在这个过程当中须要涉及到ActionMapper。
面试:
一、浏览器发送请求,通过一系列的过滤器后,到达核心过滤器(StrutsPrepareAndExecuteFilter).
二、StrutsPrepareAndExecuteFilter经过ActionMapper判断当前的请求是否须要某个Action处理,若是不须要,则走原来的流程。若是须要则把请求交给ActionProxy来处理
三、ActionProxy经过Configuration Manager询问框架的配置文件(Struts.xml),找到须要调用的Action类;
四、建立一个ActionInvocation实例,来调用Action的对应方法来获取结果集的name,在调用先后会执行相关拦截器。
五、经过结果集的Name知道对应的结果集来对浏览器进行响应。
目前企业中使用SpringMvc的比例已经远远超过Struts2,那么二者到底有什么区别,是不少初学者比较关注的问题,下面咱们就来对SpringMvc和Struts2进行各方面的比较:
1.核心控制器(前端控制器、预处理控制器):对于使用过mvc框架的人来讲这个词应该不会陌生,核心控制器的主要用途是处理全部的请求,而后对那些特殊的请求 (控制器)统一的进行处理(字符编码、文件上传、参数接受、异常处理等等),spring mvc核心控制器是Servlet,而Struts2是Filter。
2.控制器实例:Spring Mvc会比Struts快一些(理论上)。Spring Mvc是基于方法设计,而Sturts是基于对象,每次发一次请求都会实例一个action,每一个action都会被注入 属性,而Spring更像Servlet同样,只有一个实例,每次请求执行对应的方法便可(注意:因为是单例实例,因此应当避免全局变量的修改,这样会产生线程安全问题)。
3.管理方式:大部分的公司的核心架构中,就会使用到spring,而spring mvc又是spring中的一个模块,因此spring对于spring mvc的控制器管理更加简单方便,并且提供了全 注解方式进行管理,各类功能的注解都比较全面,使用简单,而struts2须要采用XML不少的配置参数来管理(虽然也能够采用注解,可是几乎没有公司那 样使用)。
4.参数传递:Struts2中自身提供多种参数接受,其实都是经过(ValueStack)进行传递和赋值,而SpringMvc是经过方法的参数进行接收。
5.学习难度:Struts更加不少新的技术点,好比拦截器、值栈及OGNL表达式,学习成本较高,springmvc 比较简单,很较少的时间都能上手。
6.intercepter 的实现机制:struts有以本身的interceptor机制,spring mvc用的是独立的AOP方式。这样致使struts的配置文件量仍是比spring mvc大,虽然struts的配置能继承,因此我以为论使用上来说,spring mvc使用更加简洁,开发效率Spring MVC确实比struts2高。spring mvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,因此说从架构自己上spring3 mvc就容易实现restful url。struts2是类级别的拦截,一个类对应一个request上下文;实现restful url要费劲,由于struts2 action的一个方法能够对应一个url;而其类属性却被全部方法共享,这也就没法用注解或其余方式标识其所属方法了。spring3 mvc的方法之间基本上独立的,独享request response数据,请求数据经过参数获取,处理结果经过ModelMap交回给框架方法之间不共享变量,而struts2搞的就比较乱,虽然方法之间 也是独立的,但其全部Action变量是共享的,这不会影响程序运行,却给咱们编码,读程序时带来麻烦。
7.spring mvc处理ajax请求,直接经过返回数据,方法中使用注解@ResponseBody,spring mvc自动帮咱们对象转换为JSON数据。而struts2是经过插件的方式进行处理。
在SpringMVC流行起来以前,Struts2在MVC框架中占核心地位,随着SpringMVC的出现,SpringMVC慢慢的取代struts2,可是不少企业都是原来搭建的框架,使用Struts2较多。
概述一:
自从Servlet3.0+的出现,Spring-web模块提供了一种免配置文件,在如Tomcat(支持Servlet3.0+)这样的Servlet容器启动时,自动调用了实现的WebApplicationInitializer(全路径org.springframework.web.WebApplicationInitializer)接口的类的onStartup方法,并将容器的ServletContext往下传递。
从Spring-web模块的API中,找到子类AbstractAnnotationConfigDispatcherServletInitializer,它间接实现了WebApplicationInitializer接口,父类onStartup方法,首先建立RootWebApplicationContext并设置ContextLoaderListner监听器;其次,注册往servletContext注册DispatcherServlet实例。
因为AbstractAnnotationConfigDispatcherServletInitializer是抽象类,Spring容器不能注入。它重写了父类建立根ApplicationContext与ServletApplicationContext方法,并抽象出两个方法(用来建立根ApplicationContext和ServletApplicationContext容器时,须要注入的组件字类节数组)。
所以 咱们只须要编写SpringMVCInitializer来继承AbstractAnnotationConfigDispatcherServletInitializer类,让它来帮咱们完成对DispatcherServlet实例的加载便可。
概述二:
如今JavaConfig配置方式在逐步取代xml配置方式。而WebApplicationInitializer能够看作是Web.xml的替代,它是一个接口。经过实现WebApplicationInitializer,在其中能够添加servlet,listener等,在加载Web项目的时候会加载这个接口实现类,从而起到web.xml相同的做用。
为了支持能够不使用web.xml。提供了ServletContainerInitializer,它能够经过SPI机制,当启动web容器的时候,会自动到添加的相应jar包下找到META-INF/services下以ServletContainerInitializer的全路径名称命名的文件,它的内容为ServletContainerInitializer实现类的全路径,将它们实例化。既然这样的话,那么SpringServletContainerInitializer做为ServletContainerInitializer的实现类,它的jar包下也应该有相应的文件。
首先,SpringServletContainerInitializer做为ServletContainerInitializer的实现类,经过SPI机制,在web容器加载的时候会自动的被调用。(这个类上还有一个注解@HandlesTypes,它的做用是将感兴趣的一些类注入到ServletContainerInitializerde), 而这个类的方法又会扫描找到WebApplicationInitializer的实现类,调用它的onStartup方法,从而起到启动web.xml相同的做用。
Servlet 3.0 做为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一块儿发布。该版本在前一版本(Servlet 2.5)的基础上提供了若干新特性用于简化 Web 应用的开发和部署。其中有几项特性的引入让开发者感到很是兴奋,同时也得到了 Java 社区的一片赞誉之声:
1.异步处理支持:有了该特性,Servlet 线程再也不须要一直阻塞,直到业务处理完毕才能再输出响应,最后才结束该 Servlet 线程。在接收到请求以后,Servlet 线程能够将耗时的操做委派给另外一个线程来完成,本身在不生成响应的状况下返回至容器。针对业务处理较耗时的状况,这将大大减小服务器资源的占用,而且提升并发处理速度。
2.新增的注解支持:该版本新增了若干注解,用于简化 Servlet、过滤器(Filter)和监听器(Listener)的声明,这使得 web.xml 部署描述文件从该版本开始再也不是必选的了。
3.可插性支持:熟悉 Struts2 的开发者必定会对其经过插件的方式与包括 Spring 在内的各类经常使用框架的整合特性记忆犹新。将相应的插件封装成 JAR 包并放在类路径下,Struts2 运行时便能自动加载这些插件。如今 Servlet 3.0 提供了相似的特性,开发者能够经过插件的方式很方便的扩充已有 Web 应用的功能,而不须要修改原有的应用。
@RequestMapping方法方法所支持的常见参数类型:
请求或响应对象(Servlet API)。能够是任何具体的请求或响应类型的对象,好比,ServletRequest或HttpServletRequest对象。
HttpSession类型的会话对象(Servlet API)。使用该类型的参数将要求这样一个session的存在,所以这样的参数永不为null。
当前请求的地区信息java.util.Locale,由已配置的最相关的地区解析器解析获得。在MVC的环境下,就是应用中配置的LocaleResolver或LocaleContextResolver
与当前请求绑定的时区信息java.util.TimeZone(java 6以上的版本)/java.time.ZoneId(java 8),由LocaleContextResolver解析获得
org.springframework.http.HttpMethod。能够拿到HTTP请求方法
包装了当前被认证用户信息的java.security.Principal
带@PathVariable标注的方法参数,其存放了URI模板变量中的值。
带@RequestParam标注的方法参数,其存放了Servlet请求中所指定的参数。参数的值会被转换成方法参数所声明的类型。
带@RequestHeader标注的方法参数,其存放了Servlet请求中所指定的HTTP请求头的值。参数的值会被转换成方法参数所声明的类型。
带@RequestBody标注的参数,提供了对HTTP请求体的存取。参数的值经过HttpMessageConverter被转换成方法参数所声明的类型。
带@RequestPart标注的参数,提供了对一个"multipart/form-data请求块(request part)内容的存取。
HttpEntity<?>类型的参数,其提供了对HTTP请求头和请求内容的存取。请求流是经过HttpMessageConverter被转换成entity对象的。
java.util.Map/org.springframework.io.Model/org.springframework.ui.ModelMap类型的参数,用以加强默认暴露给视图层的模型(model)的功能
org.springframework.web.servlet.mvc.support.RedirectAttributes类型的参数,用以指定重定向下要使用到的属性集以及添加flash属性(暂存在服务端的属性,它们会在下次重定向请求的范围中有效)。
命令或表单对象,它们用于将请求参数直接绑定到bean字段(多是经过setter方法)。你能够经过@InitBinder标注和/或HanderAdapter的配置来定制这个过程的类型转换。RequestMappingHandlerAdapter类webBindingInitializer属性的文档。这样的命令对象,以及其上的验证结果,默认会被添加到模型model中,键名默认是该命令对象类的类名——好比,some.package.OrderAddress类型的命令对象就使用属性名orderAddress类获取。ModelAttribute标注能够应用在方法参数上,用以指定该模型所用的属性名
org.springframework.validation.Errors / org.springframework.validation.BindingResult验证结果对象,用于存储前面的命令或表单对象的验证结果(紧接其前的第一个方法参数)。
org.springframework.web.bind.support.SessionStatus对象,用以标记当前的表单处理已结束。这将触发一些清理操做:@SessionAttributes在类级别标注的属性将被移除
org.springframework.web.util.UriComponentsBuilder构造器对象,用于构造当前请求URL相关的信息,好比主机名、端口号、资源类型(scheme)、上下文路径、servlet映射中的相对部分(literal part)等
BindingResult的特殊性:
在参数列表中,Errors或BindingResult参数必须紧跟在其所绑定的验证对象后面。这是由于,在参数列表中容许有多于一个的模型对象,Spring会为它们建立不一样的BindingResult实例。所以,下面这样的代码是不能工做的:
BindingResult与@ModelAttribute错误的参数次序
@RequestMapping(method = RequestMethod.POST)
public String processSubmit(@ModelAttribute("pet") Pet pet, Model model, BindingResult result) { ... }
上例中,由于在模型对象Pet和验证结果对象BindingResult中间还插了一个Model参数,这是不行的。要达到预期的效果,必须调整一下参数的次序:
@RequestMapping(method = RequestMethod.POST)
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result, Model model) { ... }
对于一些带有required属性的标注(好比@RequestParam、@RequestHeader等),JDK 1.8的java.util.Optional能够做为被它们标注的方法参数。在这种状况下,使用java.util.Optional与required=false的做用是相同的。
@RequestMapping方法方法支持的常见返回类型:
ModelAndView对象,其中model隐含填充了命令对象,以及标注了@ModelAttribute字段的存取器被调用所返回的值。
Model对象,其中视图名称默认由RequestToViewNameTranslator决定,model隐含填充了命令对象以及标注了@ModelAttribute字段的存取器被调用所返回的值
Map对象,用于暴露model,其中视图名称默认由RequestToViewNameTranslator决定,model隐含填充了命令对象以及标注了@ModelAttribute字段的存取器被调用所返回的值
View对象。其中model隐含填充了命令对象,以及标注了@ModelAttribute字段的存取器被调用所返回的值。handler方法也能够增长一个Model类型的方法参数来加强model
String对象,其值会被解析成一个逻辑视图名。其中,model将默认填充了命令对象以及标注了@ModelAttribute字段的存取器被调用所返回的值。handler方法也能够增长一个Model类型的方法参数来加强model
void。若是处理器方法中已经对response响应数据进行了处理(好比在方法参数中定义一个ServletResponse或HttpServletResponse类型的参数并直接向其响应体中写东西),那么方法能够返回void。handler方法也能够增长一个Model类型的方法参数来加强model
若是处理器方法标注了ResponseBody,那么返回类型将被写到HTTP的响应体中,而返回值会被HttpMessageConverters转换成所方法声明的参数类型。
HttpEntity<?>或ResponseEntity<?>对象,用于提供对Servlet HTTP响应头和响应内容的存取。对象体会被HttpMessageConverters转换成响应流。
HttpHeaders对象,返回一个不含响应体的response
若是返回类型不是Spring MVC默认识别的类型,则会被处理成model的一个属性并返回给视图,该属性的名称为方法级的@ModelAttribute所标注的字段名(或者以返回类型的类名做为默认的属性名)。model隐含填充了命令对象以及标注了@ModelAttribute字段的存取器被调用所返回的值
总结:
最经常使用的参数和返回类型应该是Spring MVC给你提供的抽象,好比Model、View和ModelView等概念,以及用来识别请求或者表示返回类型的标准,如@PathVariable和ResponseBody等,这些能够说时Spring MVC的核心。
另外有些参数类型可能会常用,好比须要访问HttpSession或者HttpServletRequest等原生的Servlet API,则直接声明该类型的一个参数便可。
以上类型即便在一个大型的Spring MVC项目中也不必定都须要用到。可是其中一些特性在特定的场景下很是有用。
好比,若是控制器但愿获取当前URL的主机名、端口号、资源类型(scheme)、上下文路径等信息,则在@RequestMapping方法的参数中增长一个org.springframework.web.util.UriComponentsBuilder类型便可。Spring MVC会将相关信息自动填充好,你直接使用便可。
使用@ModelAttribute、Model、Map、@SessionAttributes能便捷地将咱们的业务数据封装到模型里并交由视图解析调用。
1.@RequestParam绑定单个请求参数值
@RequestParam用于将请求参数区数据映射到功能处理方法的参数上。
public String requestparam1(@RequestParam String username)
请求中包含username参数(如/requestparam1?username=zhang),则自动传入。
public String requestparam2(@RequestParam("username") String username)
经过@RequestParam("username")明确告诉Spring Web MVC使用username进行入参。
接下来咱们看一下@RequestParam注解主要有哪些参数:
value:参数名字,即入参的请求参数名字,如username表示请求的参数区中的名字为username的参数的值将传入;
required:是否必须,默认是true,表示请求中必定要有相应的参数,不然将报404错误码;
defaultValue:默认值,表示若是请求中没有同名参数时的默认值,默认值能够是SpEL表达式,如“#{systemProperties['java.vm.version']}”。
public String requestparam4(@RequestParam(value="username",required=false) String username)
表示请求中能够没有名字为username的参数,若是没有默认为null,此处须要注意以下几点:
原子类型:必须有值,不然抛出异常,若是容许空值请使用包装类代替。
Boolean包装类型类型:默认Boolean.FALSE,其余引用类型默认为null。
public String requestparam5(
@RequestParam(value="username", required=true, defaultValue="zhang") String username)
表示若是请求中没有名字为username的参数,默认值为“zhang”。
若是请求中有多个同名的应该如何接收呢?如给用户受权时,可能授予多个权限,首先看下以下代码:
public String requestparam7(@RequestParam(value="role") String roleList)
若是请求参数相似于url?role=admin&rule=user,则实际roleList参数入参的数据为“admin,user”,即多个数据之间使用“,”分割;咱们应该使用以下方式来接收多个请求参数:
public String requestparam7(@RequestParam(value="role") String[] roleList)
或
public String requestparam8(@RequestParam(value="list") List<String> list)
2.@PathVariable绑定URI模板变量值
@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上。
@RequestMapping(value="/users/{userId}/topics/{topicId}")
public String test(
@PathVariable(value="userId") int userId,
@PathVariable(value="topicId") int topicId)
如请求的URL为“控制器URL/users/123/topics/456”,则自动将URL中模板变量{userId}和{topicId}绑定到经过@PathVariable注解的同名参数上,即入参后userId=12三、topicId=456。
3.@CookieValue绑定Cookie数据值
@CookieValue用于将请求的Cookie数据映射到功能处理方法的参数上。
public String test(@CookieValue(value="JSESSIONID", defaultValue="") String sessionId)
如上配置将自动将JSESSIONID值入参到sessionId参数上,defaultValue表示Cookie中没有JSESSIONID时默认为空。
public String test2(@CookieValue(value="JSESSIONID", defaultValue="") Cookie sessionId)
传入参数类型也能够是javax.servlet.http.Cookie类型。
@CookieValue也拥有和@RequestParam相同的三个参数,含义同样。
4.@RequestHeader绑定请求头数据
@RequestHeader用于将请求的头信息区数据映射到功能处理方法的参数上。
@RequestMapping(value="/header")
public String test(
@RequestHeader("User-Agent") String userAgent,
@RequestHeader(value="Accept") String[] accepts)
如上配置将自动将请求头“User-Agent”值入参到userAgent参数上,并将“Accept”请求头值入参到accepts参数上。测试代码在HeaderValueTypeController中。
@RequestHeader也拥有和@RequestParam相同的三个参数,含义同样。
5.@ModelAttribute绑定请求参数到命令对象
@ModelAttribute一个具备以下三个做用:
①绑定请求参数到命令对象:放在功能处理方法的入参上时,用于将多个请求参数绑定到一个命令对象,从而简化绑定流程,并且自动暴露为模型数据用于视图页面展现时使用;
②暴露表单引用对象为模型数据:放在处理器的通常方法(非功能处理方法)上时,是为表单准备要展现的表单引用对象,如注册时须要选择的所在城市等,并且在执行功能处理方法(@RequestMapping注解的方法)以前,自动添加到模型对象中,用于视图页面展现时使用;
③暴露@RequestMapping方法返回值为模型数据:放在功能处理方法的返回值上时,是暴露功能处理方法的返回值为模型数据,用于视图页面展现时使用。
1、绑定请求参数到命令对象
如用户登陆,咱们须要捕获用户登陆的请求参数(用户名、密码)并封装为用户对象,此时咱们可使用@ModelAttribute绑定多个请求参数到咱们的命令对象。
public String test1(@ModelAttribute("user") UserModel user)
它的做用是将该绑定的命令对象以“user”为名称添加到模型对象中供视图页面展现使用。咱们此时能够在视图页面使用${user.username}来获取绑定的命令对象的属性。
绑定请求参数到命令对象支持对象图导航式的绑定,如请求参数包含“?username=zhang&password=123&workInfo.city=bj”自动绑定到user中的workInfo属性的city属性中。
@RequestMapping(value="/model2/{username}")
public String test2(@ModelAttribute("model") DataBinderTestModel model) {
URI模板变量也能自动绑定到命令对象中,当你请求的URL中包含“bool=yes&schooInfo.specialty=computer&hobbyList[0]=program&hobbyList[1]=music&map[key1]=value1&map[key2]=value2&state=blocked”会自动绑定到命令对象上。
当URI模板变量和请求参数同名时,URI模板变量具备高优先权。
2、暴露表单引用对象为模型数据
@ModelAttribute("cityList")
public List<String> cityList() {
return Arrays.asList("北京", "山东");
}
如上代码会在执行功能处理方法以前执行,并将其自动添加到模型对象中,在功能处理方法中调用Model 入参的containsAttribute("cityList")将会返回true。
@ModelAttribute("user") //①
public UserModel getUser(@RequestParam(value="username", defaultValue="") String username) {
//TODO 去数据库根据用户名查找用户对象
UserModel user = new UserModel();
user.setRealname("zhang");
return user;
}
如你要修改用户资料时通常须要根据用户的编号/用户名查找用户来进行编辑,此时能够经过如上代码查找要编辑的用户。
也能够进行一些默认值的处理。
@RequestMapping(value="/model1") //②
public String test1(@ModelAttribute("user") UserModel user, Model model)
此处咱们看到①和②有同名的命令对象,那Spring Web MVC内部如何处理的呢:
(一、首先执行@ModelAttribute注解的方法,准备视图展现时所须要的模型数据;@ModelAttribute注解方法形式参数规则和@RequestMapping规则同样,如能够有@RequestParam等;
(二、执行@RequestMapping注解方法,进行模型绑定时首先查找模型数据中是否含有同名对象,若是有直接使用,若是没有经过反射建立一个,所以②处的user将使用①处返回的命令对象。即②处的user等于①处的user。
3、暴露@RequestMapping方法返回值为模型数据
public @ModelAttribute("user2") UserModel test3(@ModelAttribute("user2") UserModel user)
你们能够看到返回值类型是命令对象类型,并且经过@ModelAttribute("user2")注解,此时会暴露返回值到模型数据(名字为user2)中供视图展现使用。那哪一个视图应该展现呢?此时Spring Web MVC会根据RequestToViewNameTranslator进行逻辑视图名的翻译。
此时又有问题了,@RequestMapping注解方法的入参user暴露到模型数据中的名字也是user2,其实咱们能猜到:
(三、@ModelAttribute注解的返回值会覆盖@RequestMapping注解方法中的@ModelAttribute注解的同名命令对象。
4、匿名绑定命令参数
public String test4(@ModelAttribute UserModel user, Model model)
或
public String test5(UserModel user, Model model)
此时咱们没有为命令对象提供暴露到模型数据中的名字,此时的名字是什么呢?Spring Web MVC自动将简单类名(首字母小写)做为名字暴露,如“cn.javass.chapter6.model.UserModel”暴露的名字为“userModel”。
public @ModelAttribute List<String> test6()
或
public @ModelAttribute List<UserModel> test7()
对于集合类型(Collection接口的实现者们,包括数组),生成的模型对象属性名为“简单类名(首字母小写)”+“List”,如List<String>生成的模型对象属性名为“stringList”,List<UserModel>生成的模型对象属性名为“userModelList”。
其余状况一概都是使用简单类名(首字母小写)做为模型对象属性名,如Map<String, UserModel>类型的模型对象属性名为“map”。
6.@SessionAttributes绑定命令对象到session
有时候咱们须要在屡次请求之间保持数据,通常状况须要咱们明确的调用HttpSession的API来存取会话数据,如多步骤提交的表单。Spring Web MVC提供了@SessionAttributes进行请求间透明的存取会话数据。
//一、在控制器类头上添加@SessionAttributes注解
@SessionAttributes(value = {"user"}) //①
public class SessionAttributeController
//二、@ModelAttribute注解的方法进行表单引用对象的建立
@ModelAttribute("user") //②
public UserModel initUser()
//三、@RequestMapping注解方法的@ModelAttribute注解的参数进行命令对象的绑定
@RequestMapping("/session1") //③
public String session1(@ModelAttribute("user") UserModel user)
//四、经过SessionStatus的setComplete()方法清除@SessionAttributes指定的会话数据
@RequestMapping("/session2") //③
public String session(@ModelAttribute("user") UserModel user, SessionStatus status) {
if(true) { //④
status.setComplete();
}
return "success";
}
@SessionAttributes(value = {"user"})含义:
@SessionAttributes(value = {"user"}) 标识将模型数据中的名字为“user” 的对象存储到会话中(默认HttpSession),此处value指定将模型数据中的哪些数据(名字进行匹配)存储到会话中,此外还有一个types属性表示模型数据中的哪些类型的对象存储到会话范围内,若是同时指定value和types属性则那些名字和类型都匹配的对象才能存储到会话范围内。
包含@SessionAttributes的执行流程以下所示:
① 首先根据@SessionAttributes注解信息查找会话内的对象放入到模型数据中;
② 执行@ModelAttribute注解的方法:若是模型数据中包含同名的数据,则不执行@ModelAttribute注解方法进行准备表单引用数据,而是使用①步骤中的会话数据;若是模型数据中不包含同名的数据,执行@ModelAttribute注解的方法并将返回值添加到模型数据中;
③ 执行@RequestMapping方法,绑定@ModelAttribute注解的参数:查找模型数据中是否有@ModelAttribute注解的同名对象,若是有直接使用,不然经过反射建立一个;并将请求参数绑定到该命令对象;
此处须要注意:若是使用@SessionAttributes注解控制器类以后,③步骤必定是从模型对象中取得同名的命令对象,若是模型数据中不存在将抛出HttpSessionRequiredException Expected session attribute ‘user’(Spring3.1)
或HttpSessionRequiredException Session attribute ‘user’ required - not found in session(Spring3.0)异常。
④ 若是会话能够销毁了,如多步骤提交表单的最后一步,此时能够调用SessionStatus对象的setComplete()标识当前会话的@SessionAttributes指定的数据能够清理了,此时当@RequestMapping功能处理方法执行完毕会进行清理会话数据。
咱们经过Spring Web MVC的源代码验证一下吧,此处咱们分析的是Spring3.1的RequestMappingHandlerAdapter,读者能够自行验证Spring3.0的AnnotationMethodHandlerAdapter,流程同样:
(一、RequestMappingHandlerAdapter.invokeHandlerMethod
//一、RequestMappingHandlerAdapter首先调用ModelFactory的initModel方法准备模型数据:
modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);
//二、调用@RequestMapping注解的功能处理方法
requestMappingMethod.invokeAndHandle(webRequest, mavContainer);
//三、更新/合并模型数据
modelFactory.updateModel(webRequest, mavContainer);
(二、ModelFactory.initModel
Map<String, ?> attributesInSession = this.sessionAttributesHandler.retrieveAttributes(request);
//1.一、将与@SessionAttributes注解相关的会话对象放入模型数据中
mavContainer.mergeAttributes(attributesInSession);
//1.二、调用@ModelAttribute方法添加表单引用对象
invokeModelAttributeMethods(request, mavContainer);
//1.三、验证模型数据中是否包含@SessionAttributes注解相关的会话对象,不包含抛出异常
for (String name : findSessionAttributeArguments(handlerMethod)) {
if (!mavContainer.containsAttribute(name)) {
//1.四、此处防止在@ModelAttribute注解方法又添加了会话对象
//如在@ModelAttribute注解方法调用session.setAttribute("user", new UserModel());
Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);
if (value == null) {
throw new HttpSessionRequiredException("Expected session attribute '" + name + "'");
}
mavContainer.addAttribute(name, value);
}
(三、ModelFactory.invokeModelAttributeMethods
for (InvocableHandlerMethod attrMethod : this.attributeMethods) {
String modelName = attrMethod.getMethodAnnotation(ModelAttribute.class).value();
//1.2.一、若是模型数据中包含同名数据则再也不添加
if (mavContainer.containsAttribute(modelName)) {
continue;
}
//1.2.二、调用@ModelAttribute注解方法并将返回值添加到模型数据中,此处省略实现代码
}
(四、requestMappingMethod.invokeAndHandle 调用功能处理方法,此处省略
(五、ModelFactory.updateMode 更新模型数据
//3.一、若是会话被标识为完成,此时从会话中清除@SessionAttributes注解相关的会话对象
if (mavContainer.getSessionStatus().isComplete()){
this.sessionAttributesHandler.cleanupAttributes(request);
}
//3.二、若是会话没有完成,将模型数据中的@SessionAttributes注解相关的对象添加到会话中
else {
this.sessionAttributesHandler.storeAttributes(request, mavContainer.getModel());
}
//省略部分代码
到此@SessionAtrribute介绍完毕。
多步骤提交表单须要考虑会话超时问题,这种方式可能对用户不太友好,咱们能够采起隐藏表单(即当前步骤将其余步骤的表单隐藏)或表单数据存数据库(每步骤更新下数据库数据)等方案解决。
7.@Value绑定SpEL表示式
@Value用于将一个SpEL表达式结果映射到到功能处理方法的参数上。
public String test(@Value("#{systemProperties['java.vm.version']}") String jvmVersion)
到此数据绑定咱们就介绍完了。
SpringMVC用于处理视图最重要的两个接口是ViewResolver和View。ViewResolver的主要做用是把一个逻辑上的视图名称解析为一个真正的视图,SpringMVC中用于把View对象呈现给客户端的是View对象自己,而ViewResolver只是把逻辑视图名称解析为对象的View对象。View接口的主要做用是用于处理视图,而后返回给客户端。
Spring为咱们提供了很是多的视图解析器,下面将列举一些视图解析器:
AbstractCachingViewResolver:这是一个抽象类,这种视图解析器会把它曾经解析过的视图保存起来,而后每次要解析视图的时候先从缓存里面找,若是找到了对应的视图就直接返回,若是没有就建立一个新的视图对象,而后把它放到一个用于缓存的map中,接着再把新建的视图返回。使用这种视图缓存的方式能够把解析视图的性能问题降到最低。
UrlBasedViewResolver:它是对ViewResolver的一种简单实现,并且继承了AbstractCachingViewResolver,主要就是提供的一种拼接URL的方式来解析视图,它可让咱们经过prefix属性指定一个指定的前缀,经过suffix属性指定一个指定的后缀,而后把返回的逻辑视图名称加上指定的前缀和后缀就是指定的视图URL了。如prefix=/WEB-INF/jsps/,suffix=.jsp,返回的视图名称viewName=test/indx,则UrlBasedViewResolver解析出来的视图URL就是/WEB-INF/jsps/test/index.jsp。默认的prefix和suffix都是空串。URLBasedViewResolver支持返回的视图名称中包含redirect:前缀,这样就能够支持URL在客户端的跳转,如当返回的视图名称是”redirect:test.do”的时候,URLBasedViewResolver发现返回的视图名称包含”redirect:”前缀,因而把返回的视图名称前缀”redirect:”去掉,取后面的test.do组成一个RedirectView,RedirectView中将把请求返回的模型属性组合成查询参数的形式组合到redirect的URL后面,而后调用HttpServletResponse对象的sendRedirect方法进行重定向。一样URLBasedViewResolver还支持forword:前缀,对于视图名称中包含forword:前缀的视图名称将会被封装成一个InternalResourceView对象,而后在服务器端利用RequestDispatcher的forword方式跳转到指定的地址。使用UrlBasedViewResolver的时候必须指定属性viewClass,表示解析成哪一种视图,通常使用较多的就是InternalResourceView,利用它来展示jsp,可是当咱们使用JSTL的时候咱们必须使用JstlView。下面是一段UrlBasedViewResolver的定义,根据该定义,当返回的逻辑视图名称是test的时候,UrlBasedViewResolver将把逻辑视图名称加上定义好的前缀和后缀,即“/WEB-INF/test.jsp”,而后新建一个viewClass属性指定的视图类型予以返回,即返回一个url为“/WEB-INF/test.jsp”的InternalResourceView对象。
InternalResourceViewResolver:它是URLBasedViewResolver的子类,因此URLBasedViewResolver支持的特性它都支持。在实际应用中InternalResourceViewResolver也是使用的最普遍的一个视图解析器。那么InternalResourceViewResolver有什么本身独有的特性呢?单从字面意思来看,咱们能够把InternalResourceViewResolver解释为内部资源视图解析器,这就是InternalResourceViewResolver的一个特性。InternalResourceViewResolver会把返回的视图名称都解析为InternalResourceView对象,InternalResourceView会把Controller处理器方法返回的模型属性都存放到对应的request属性中,而后经过RequestDispatcher在服务器端把请求forword重定向到目标URL。好比在InternalResourceViewResolver中定义了prefix=/WEB-INF/,suffix=.jsp,而后请求的Controller处理器方法返回的视图名称为test,那么这个时候InternalResourceViewResolver就会把test解析为一个InternalResourceView对象,先把返回的模型属性都存放到对应的HttpServletRequest属性中,而后利用RequestDispatcher在服务器端把请求forword到/WEB-INF/test.jsp。这就是InternalResourceViewResolver一个很是重要的特性,咱们都知道存放在/WEB-INF/下面的内容是不能直接经过request请求的方式请求到的,为了安全性考虑,咱们一般会把jsp文件放在WEB-INF目录下,而InternalResourceView在服务器端跳转的方式能够很好的解决这个问题。下面是一个InternalResourceViewResolver的定义,根据该定义当返回的逻辑视图名称是test的时候,InternalResourceViewResolver会给它加上定义好的前缀和后缀,组成“/WEB-INF/test.jsp”的形式,而后把它当作一个InternalResourceView的url新建一个InternalResourceView对象返回。
XmlViewResolver:它继承自AbstractCachingViewResolver抽象类,因此它也是支持视图缓存的。XmlViewResolver须要给定一个xml配置文件,该文件将使用和Spring的bean工厂配置文件同样的DTD定义,因此其实该文件就是用来定义视图的bean对象的。在该文件中定义的每个视图的bean对象都给定一个名字,而后XmlViewResolver将根据Controller处理器方法返回的逻辑视图名称到XmlViewResolver指定的配置文件中寻找对应名称的视图bean用于处理视图。该配置文件默认是/WEB-INF/views.xml文件,若是不使用默认值的时候能够在XmlViewResolver的location属性中指定它的位置。XmlViewResolver还实现了Ordered接口,所以咱们能够经过其order属性来指定在ViewResolver链中它所处的位置,order的值越小优先级越高。
ResourceBundleViewResolver:它和XmlViewResolver同样,也是继承自AbstractCachingViewResolver,可是它缓存的不是视图,这个会在后面有说到。和XmlViewResolver同样它也须要有一个配置文件来定义逻辑视图名称和真正的View对象的对应关系,不一样的是ResourceBundleViewResolver的配置文件是一个属性文件,并且必须是放在classpath路径下面的,默认状况下这个配置文件是在classpath根目录下的views.properties文件,若是不使用默认值的话,则能够经过属性baseName或baseNames来指定。baseName只是指定一个基名称,Spring会在指定的classpath根目录下寻找以指定的baseName开始的属性文件进行View解析,如指定的baseName是base,那么base.properties、baseabc.properties等等以base开始的属性文件都会被Spring当作ResourceBundleViewResolver解析视图的资源文件。
FreeMarkerViewResolver、VolocityViewResolver:这两个视图解析器都是UrlBasedViewResolver的子类。FreeMarkerViewResolver会把Controller处理方法返回的逻辑视图解析为FreeMarkerView,而VolocityViewResolver会把返回的逻辑视图解析为VolocityView。由于这两个视图解析器相似,因此这里我就只挑FreeMarkerViewResolver来作一个简单的讲解。FreeMarkerViewResolver和VilocityViewResolver都继承了UrlBasedViewResolver。对于FreeMarkerViewResolver而言,它会按照UrlBasedViewResolver拼接URL的方式进行视图路径的解析。可是使用FreeMarkerViewResolver的时候不须要咱们指定其viewClass,由于FreeMarkerViewResolver中已经把viewClass定死为FreeMarkerView了。
视图解析链:
在SpringMVC中能够同时定义多个ViewResolver视图解析器,而后它们会组成一个ViewResolver链。当Controller处理器方法返回一个逻辑视图名称后,ViewResolver链将根据其中ViewResolver的优先级来进行处理。全部的ViewResolver都实现了Ordered接口,在Spring中实现了这个接口的类都是能够排序的。在ViewResolver中是经过order属性来指定顺序的,默认都是最大值。因此咱们能够经过指定ViewResolver的order属性来实现ViewResolver的优先级,order属性是Integer类型,order越小,对应的ViewResolver将有越高的解析视图的权利,因此第一个进行解析的将是ViewResolver链中order值最小的那个。当一个ViewResolver在进行视图解析后返回的View对象是null的话就表示该ViewResolver不能解析该视图,这个时候若是还存在其余order值比它大的ViewResolver就会调用剩余的ViewResolver中的order值最小的那个来解析该视图,依此类推。当ViewResolver在进行视图解析后返回的是一个非空的View对象的时候,就表示该ViewResolver可以解析该视图,那么视图解析这一步就完成了,后续的ViewResolver将不会再用来解析该视图。当定义的全部ViewResolver都不能解析该视图的时候,Spring就会抛出一个异常。
基于Spring支持的这种ViewResolver链模式,咱们就能够在SpringMVC应用中同时定义多个ViewResolver,给定不一样的order值,这样咱们就能够对特定的视图特定处理,以此来支持同一应用中有多种视图类型。注意:像InternalResourceViewResolver这种能解析全部的视图,即永远能返回一个非空View对象的ViewResolver必定要把它放在ViewResolver链的最后面。
Spring MVC 3.1版本加了一个颇有用的特性,Flash属性,它能解决一个长久以来缺乏解决的问题,一个POST/Redirect/GET模式问题。
一般当咱们生成一次http重定向请求的时候,被存储到请求数据会丢失,使得下一次GET请求不可能访问到此次请求中的一些有用的信息。
Flash attributes 的到来就是为了处理这一状况. Flash attributes 为一个请求存储意图为另一个请求所使用的属性提供了一条途径. Flash attributes 在对请求的重定向生效以前被临时存储(一般是在session)中,而且在重定向以后被当即移除。
为了这样作, Flash 特性使用了两个集合. FlashMap 被用来管理 flash attributes 而 FlashMapManager 则被用来存储,获取和管理 FlashMap 实体。
对于每一次请求一个 “input” flash map 会被建立,来存储来自任何以前请求的 flash attribute 还有一个 “output” flash map 会被建立,来存储任何咱们存储在这个请求中的,以后的请求参数。
要想在你的 Spring MVC 应用中使用 Flash attribute,要用 3.1 版本或以上。而且要在 spring-servlet.xml 文件中加入 mvc:annotation-driven。
<mvc:annotation-driven />
这些都完成以后,Flash attribute 就会自动设为“开启”,以供使用了。只需在你的 Spring controller 方法中加入RedirectAttributes redirectAttributes。
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
//...
@RequestMapping(value="addcustomer", method=RequestMethod.POST)
public String addCustomer(@ModelAttribute("customer") Customer customer,
final RedirectAttributes redirectAttributes) {
//...
redirectAttributes.addFlashAttribute("message", "Successfully added..");
//...
return "redirect:some_other_request_name";
}
addFlashAttribute 方法会自动向 output flash map 中添加给定的参数,并将它传递给后续的请求。
Spring MVC处理异常有3种方式: (1) 使用Spring MVC提供的简单异常处理器 SimpleMappingExceptionResolver; (2) 实现Spring的异常处理接口HandlerExceptionResolver 自定义本身的异常处理器; (3) 使用@ExceptionHandler注解实现异常处理;
自定义登陆异常:
/**
* @author: 肖德子裕
* @date: 2018/11/05 11:26
* @description: 自定义登陆异常
*/
public class UserException extends RuntimeException{
public UserException(String message) {
super(message);
}
public UserException(String message, Throwable cause) {
super(message, cause);
}
public UserException(Throwable cause) {
super(cause);
}
}
/**
* @author: 肖德子裕
* @date: 2018/11/05 11:34
* @description: 全局异常处理
*/
@ControllerAdvice("com.ex.controller")
public class ExceptionAdvice {
/**
* 全局异常处理方法
* 用于处理用户登录异常
* @param e
* @return
*/
@ExceptionHandler(UserException.class)
@ResponseBody
public ResponseVO handlerLoginException(RuntimeException e){
ResponseVO vo = new ResponseVO();
vo.setCode(401);
vo.setMessage(e.getMessage());
return vo;
}
/**
* 全局异常处理方法
* 用于处理crud操做
* @param e
* @return
*/
@ExceptionHandler(DataAccessException.class)
@ResponseBody
public ResponseVO handlerDataAccessException(RuntimeException e){
ResponseVO vo = new ResponseVO();
vo.setCode(500);
vo.setMessage(e.getMessage());
return vo;
}
}
/**
* @author: 肖德子裕
* @date: 2018/11/05 11:21
* @description: 用户操做Servie
*/
@Service
public class UserServiceImpl implements UserServie {
@Autowired
private UserDao userDao;
@Override
public User login(User user) {
User newUser = userDao.getUserByName(user.getUserName());
if(newUser == null){
throw new UserException("用户不存在");
}
if(!user.getPassWord().equals(newUser.getPassWord())){
throw new UserException("密码错误");
}
return newUser;
}
@Override
public void addUser(User user) {
userDao.saveUser(user);
}
}
过滤器的实现:
/**
* @author: 肖德子裕
* @date: 2018/8/21 10:29
* @description: 权限过滤器
*/
public class UserLoginPrivilegeFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest)request;
HttpServletResponse resp=(HttpServletResponse)response;
//效验用户是否登录,即检查session是否存在用户对象
HttpSession session=req.getSession();
//判断用户是否登录,没登录不能提交订单
User user=(User)session.getAttribute("user");
if (user==null){
//跳转到登录页
resp.sendRedirect(req.getContextPath()+"/login.jsp");
return;
}
//放行
chain.doFilter(req, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
须要在xml文件中配置:
<!-- 用户是否登录 -->
<filter>
<filter-name>UserLoginPrivilegeFilter</filter-name>
<filter-class>com.itheima.web.filter.UserLoginPrivilegeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UserLoginPrivilegeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
拦截器的实现:
/**
* @author: 肖德子裕
* @date: 2018/9/12 15:25
* @description: 拦截器类1
*/
public class Interceptor1 implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
// TODO Auto-generated method stub
System.out.println("方法前 1");
//判断用户是否登录 若是没有登录 重定向到登录页面 不放行 若是登录了 就放行了
// URL http://localhost:8080/springmvc-mybatis/login.action
//URI /login.action
String requestURI = request.getRequestURI();
if(!requestURI.contains("/login")){
String username = (String) request.getSession().getAttribute("USER_SESSION");
if(null == username){
response.sendRedirect(request.getContextPath() + "/item/login.action");
//不放行
return false;
}
}
//放行
return true;
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("方法后 1");
}
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("页面渲染后 1");
}
}
须要在springmvc中配置:
<!-- Springmvc的拦截器 -->
<mvc:interceptors>
<!-- 多个拦截器;运行时及其复杂 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<!-- 自定义的拦截器类 -->
<bean class="com.interceptor.Interceptor1"/>
</mvc:interceptor>
<!-- <mvc:interceptor>
<mvc:mapping path="/**"/>
自定义的拦截器类
<bean class="com.interceptor.Interceptor2"/>
</mvc:interceptor> -->
</mvc:interceptors>
拦截规范:
/* 拦截全部 jsp js png css 真的全拦截 建议不使用
*.action *.do 拦截以do action 结尾的请求 确定能使用
/ 拦截全部 (不包括jsp) (包含.js .png.css) 强烈建议使用