什么是Spring MVC
MVC 模型-视图-控制,用java实现mvc模式的一个web框架。
将复杂的web应用开发简化进行解耦,方便于程序员之间配合开发提高效率。
Spring mvc优点
支持多种视图。ThymeleafView、FreeMarkerView、AbstractPdfView等。
可以天然使用IOC和AOP。
模块分工明确,DispatchServlet 前端控制器、handlerMapping 请求映射处理器、HandlerAdapter 适配器、viewResolver 视图解析器。
DispatcherServlet作用
接收请求、响应结果、组合各模块间的调用
Spring MVC框架的控制器?
控制器就是根据请求路径,访问不通过的处理器最后返回视图。
注解原理是什么
注解本质是一个继承了Annotation的特殊接口,使用注解需要配合java的反射机制完成,相应参数的判断跟功能的增强。
Spring MVC常用的注解
@RequestMapping
@RequestBody
@ResponseBody
SpingMvc中的控制器的注解
@Controller
@RestController
@Controller注解的作用
@Controller 用于标记在一个类上,使用它标记的类就是一个Spring MVC Controller 对象。
@RequestMapping注解
value, method
- value: 指定请求的实际地址,指定的地址可以是URI Template
- method: 指定请求的method类型, GET、POST、PUT、DELETE等;
consumes,produces
consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
params,headers
- params: 指定request中必须包含某些参数值。
- headers: 指定request中必须包含某些指定的header参数。
@PathVariable和@RequestParam的区别
请求路径上{XXX}变量值,可以通过@PathVariable来获取
@RequestParam用来获得静态的URL请求入参
Spring MVC与Struts2区别
相同点
都是基于mvc的表现层框架,都用于web项目的开发。
不同点
前端控制器不一样。Spring MVC的前端控制器是servlet:DispatcherServlet。struts2的前端控制器是filter:StrutsPreparedAndExcutorFilter。
请求参数的接收方式不一样。Spring MVC是使用方法的形参接收请求的参数,基于方法的开发,线程安全,可以设计为单例或者多例的开发,推荐使用单例模式的开发(执行效率更高),默认就是单例开发模式。struts2是通过类的成员变量接收请求的参数,是基于类的开发,线程不安全,只能设计为多例的开发。
Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,Spring MVC通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。
Spring MVC怎么样设定重定向和转发
转发:在返回值前面加"forward:“,例如"forward:XXX.do?XXX=XXX”
重定向:在返回值前面加"redirect:“,例如"redirect:http://XXXX”
转发:由服务器进行页面跳转
重定向:浏览器进行跳转
Spring MVC和AJAX 交互
@RequestBody 接收json数据
@ResponseBody 响应JSON数据
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
请求中文乱码
post请求乱码
web配置文件设置 CharacterEncodingFilter设置为对应的编码格式。
get请求中文参数出现乱码
1.修改tomcat配置文件
Connector标签中,添加 URIEncoding 属性。
2.对参数进行重新编码
new String(xxx.getBytes("旧编码格式"), "新编码格式")
Spring MVC的异常处理
- @ExceptionHandler-处理局部异常
注意:该注解不是加在产生异常的方法上,而是加在处理异常的方法上。
使用局部异常处理,仅能处理某个 Controller 中的异常。
@ ExceptionHandler 需要进行异常处理的方法必须与出错的方法在同一个 Controller里面。
- HandlerExceptionResolver-处理全局异常
HandlerExceptionResolver 处理程序异常,包括处理器异常、数据绑定异常以及控制器执行时发生的异常。
实现HandlerExceptionResolver接口,并且将该实现类注册到容器中。
- SimpleMappingExceptionResolver-处理全局异常
它将异常类名映射为视图名,即发生异常时使用对应的视图作为返回结果。
- @ControllerAdvice+@ExceptionHandler
@controlleradvice + @ ExceptionHandler 也可以实现全局的异常捕捉。
如何设置请求方式
@RequestMapping注解里面加上method=RequestMethod.GET
Spring MVC 返回值类型
String, ModelAndView
Model、ModelMap和ModelAndView
Model只是用来传输数据的,并不会进行业务的寻址。
ModelAndView 可以进行业务寻址的 。
ModelMap对象主要用于传递控制方法处理数据到结果页面。
注意:Model是每一次请求可以自动创建,但是ModelAndView 是需要我们自己去new的。
ModelMap里面的数据放入Session
类上面加上@SessionAttributes注解,里面包含的字符串就是要放入session里面的key。
@SessionAttributes(types=XXX.class)会将model中所有类型为 XXX的属性添加到会话中。@SessionAttributes(value={“xxx1”, “xxx2”}) 会将model中属性名为xxx1和xxx2的属性添加到会话中。@SessionAttributes(types={XXX1.class, XXX2.class}) 会将model中所有类型为 XXX1和XXX2的属性添加到会话中。@SessionAttributes(value={“xxx1”,“xxx2”},types={XXX.class})会将model中属性名为xxx1和xxx2以及类型为XXX的属性添加到会话中。Spring MVC 编写拦截器
两种实现方式:
HandlerInterceptor接口
HandlerInterceptor接口中的方法都是default的,表示不强制重写方法。
但是一般会实现这三个: preHandler、postHandler、afterCompletion
HandleInterceptor拦截器会对请求进行两次拦截:
controller中的void方法会导致springmvc使用你的请求url作为视图名称,然后它在渲染视图之前会检查你的视图名称,发现这视图会导致循环请求,就抛出一个ServletException,tomcat截取到这个异常后就转发到/error页面,就在这个转发的过程中导致了springmvc重新开始DispatcherServlet的整个流程,所以拦截器自然就执行了多次。
在controller(非restController)下:方法返回值类型为String类型或者Void类型(使用请求url作为视图名称),并且不存在对应的视图。都会导致多次拦截。
DispatcherServlet 中applyDefaultViewName(),获取返回值void 获取默认视图名称,默认视图名称就是requestMapping的值。
渲染视图之前springmvc还做了个判断,就是看你的视图名称是不是本次请的uri中的一部分或者和uri一样,如果是的话,就会抛出一个异常,是一个循环视图路径。 InternalResourceView类 prepareForRendering(),会报 ServletExecption。
解决方法:
重写RequestMappingHandlerAdapter和ViewNameMethodReturnValueHandler这两个类,并将其注入容器中。
ModelAndViewContainer.setRequestHandled(true);//本次请求已经处理完毕,可以直接放行了WebRequestInterceptor接口
WebRequestInterceptor只有preHandle方法与HandlerInterceptor接口中的preHandle方法不同外,其他都是一样的。
WebRequestInterceptor是spring对HttpServletRequest的封装,所有的更改都会记录在HttpServletRequest中。
小结:
WebRequestInterceptor 和 HandlerInterceptor 中 preHandler方法的区别:
WebRequestInterceptor中该方法只起到对request数据查看修改的作用。preHandle是没有返回值的,说明该方法中的逻辑并不影响后续的方法执行。
HandlerInterceptor 可以根据条件直接返回是否进行拦截(又返回值)。 preHandle方法中就直接拒绝请求进入controller方法。
WebApplicationContext
WebApplicationContext 继承了ApplicationContext,增加了一些web相关的功能。
怎么解决 拦截器拦截 静态资源
preHandler方法中添加下面代码:
if(!(hanlder instanceof HandlerMethod )){ return true;}