springmvc-完整篇
本文根据学习视频做的笔记,视频来源-Bilibili:尚硅谷SpringMVC实战教程完整版(spring mvc框架源码解析)
一、@RequestMapping("")映射请求
修饰方法、类
处理哪一个url
1、参数:
- value:请求url
- method:请求方法
RequestMethod.POST
等 - params:请求参数
- heads:请求头
params 和 heads支持简单的表达式:
param1:表示请求必须包含名为param1的请求参数
!param1:表示请求不能包含名为param1的请求参数
param1 != value1:表示请求包含名为param1的请求参数,但其值不能为value1
{"param1=value1","param2"}:请求必须包含名为param1和param2的两个请求参数,且param1参数的值必须为value1
2、映射请求规则:Ant
-
?
:匹配一个字符 -
*
:匹配一层任意个字符 -
**
:匹配多层路径
3、@PathVariable映射URL绑定的占位符
@RequestMapping("/delete/{id}")
public String delete(@PathVariable("id") Integer id){
...
}
REST
Representational State Transfer:资源表现层状态转化;http协议里,四个表示操作方式的动词:GET(获取)、POST(新增)、PUT(修改)、DELETE(删除)。
HiddenHttpMethodFilter:spring3.0添加的过滤器,可以将请求转换为标准的http方法,支持put与delete请求。前端post请求中添加参数_method指定put或者delete:
Rest风格的url:
新增:/order POST
获得:/order/{id} GET
修改:/order/{id} PUT
删除:/order/{id} DELETE
如何发放PUT请求和DELETE请求:配置HiddenHttpMethodFilter,发送post请求,在post请求修改name="_method"的隐藏域,值为PUT或DELETE
二、映射请求参数 & 请求参数
1、@RequestParam
绑定请求参数:(@RequestParam("") String sn)
- value:参数名称
- required:参数是否必需
- defaultValue:参数的默认值(为null时)
2、@RequestHeader
映射请求头参数:@RequestHeader("") String sn)
3、@CookieValue
处理参数绑定cookie值(请求头中Cookie中):@CookieValue("") String sn)`
4、POJO自动绑定
spring Mvc 会按请求参数名和POJO属性名进行自动匹配,自动为该对象填充属性值,支持级联属性。
5、使用原生ServletAPI参数类型
- HttpServletRequest
- HttpServletResponse
- HttpSession
- java.security.Principal
- Local
- InputStream
- OutputStream
- Reader
- Writer
三、处理模型数据
1、ModelAndView
目标方法的返回值可以是ModelAndView类型。其中可以包含视图和模型信息。
SpringMvc 会把ModelAndView的model中数据放入到request域对象中
ModelAndView modelandview = new ModelAndView(viewName);
modelandview .addObject("参数名",Object);
#页面(jsp)中
{requestScope.参数名}
2、Map以及Model
目标方法可以添加Map类型(也可以是Model类型或ModelMap类型)的参数。
会将map放入到request请求域对象中
public String testMap(Map map){
map.add("参数名",Object);
}
3、@SessionAttributes
修饰在类上不能修饰方法,将类中的请求方法中符合条件的request请求域的值放到session域中,有value和type两种筛选条件。
- value:request中Model的map的key值
- type:符合request中Model的map的value值的类型
4、@ModelAttribute
修饰方法: 有该标记的方法,会在每个目标方法执行之前被SpringMvc调用
@ModelAttribute
method (@RequestParam(value="id",required=false) Integer id,Mapmap){
map.put(...)
}
修饰参数:作为@ModelAttribute方法中Map的key值
同类中其他方法参数如果没有值,将会取map中的值,注意:在@ModelAttribute修饰的方法中,放入到Map的jkey需要和方法入参类型的小写一致
源码分析:
- 调用@ModelAttribute 注解修饰的方法。实际上把@ModelAttribute方法中Map中的数据放在implicitModel中。
- 解析请求处理器的目标参数,实际上该目标参数来自于WebDataBinder对象的target属性
1)创建WebDataBinder对象:
①确定objectName属性:若传入的attrName属性值为"",则objectName为类名第一个字母小写。
*
注意:attrName。若目标方法的POJO属性使用了@ModelAttribute来修饰,则attrName值即为@ModelAttribute的value属性值
②确定target属性
在implicitModel中查找attrName对象的属性值。若存在,ok
*
若不存在:则验证当前Handler是否使用了@SessionAttributes进行修饰,若使用了,尝试从Session中获取attrName所对应的属性值。若session中没有对应的属性值,则抛出异常。
若Handler没有使用@SessionAttributes进行修饰,或@SessionAttributes中没有使用value值指定的key和attrName想匹配,则通过反射创建了POJO对象
2)SpringMvc把表单的请求参数赋给WebDataBinder的target对应的属性
3)*
SpringMvc会把WebDataBinder的attrName和target给到imiplicitModel。进而传到request域对象中。
4)把WebDataBinder的target作为参数传递给目标方法的入参
四、视图和视图解析器
对于返回String、view或ModeMap等处理方法,Spring mvc 会在内部借助视图解析器(ViewResolver)将它们装配成一个ModelAndView对象,包含了逻辑名和模型对象的视图。
1、InternalResourceViewResolver
针对jsp页面的视图解析器
2、JSTLViewResolver
若项目中使用了JSTL,则SpringMVC会自动把视图由InternalResourceView转为JstlView。
3、使用jstl的fmt国际化
引入jstl,配置国际化资源文件(ResourceBundleMessageSource)
4、配置mvc:view-controller直接转发页面
可以直接转发相应转发的页面,无需再经过Handler的方法。
在实际开发中需要配置
以还原返回上一页面效果
5、使用BeanNameViewResolver自定义view
写一个类继承View,实现getContentType和render方法,需要@Component添加至容器;
配置视图解析器BeanNameViewResolver,order属性定义视图解析器的优先级,值越小优先级越高。
可以使用此方法实现用java代码实现Excel视图。
6、重定向
如果返回的字符串中带forward:
或redict:
时,Spring mvc将会对他们特殊处理,分别进行重定向和转发操作
7、jstl 使用from中的modelAttribute属性
form需要有一个默认的modelAttribute属性,从handler中指定相同的key值,达到回显的效果。
8、处理静态资源
在Springmvc 配置文件中配置
。
对进入DispatcherServlet的请求进行筛选,如果是没有映射的请求,将请求交有web应用服务器默认的Servlet处理。
五、数据转换、格式化、校验
1、数据绑定源码分析:
1)Spring mvc主框架将ServletRequest对象及目标方法的入参实例传递给WebDataBinderFactory实例,以创建DataBinder实例对象
2)DataBinder调用装配在Spring mvc上下文中的ConversionService组件进行数据类型转换、数据格式化工作。将Servlet中的请求信息填充到入参对象中
3)调用validator组件对已经绑定了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果BindingData对象
4)Spring mvc抽取BindingResult中的入参对象和校验错误对象,将它们赋值给处理方法的响应入参
2、自定义类型转换器
ConversionService是Spring类型转换体系的核心接口。
可以利用ConversionServiceFactoryBean在Spring的IOC容器中定义一个ConversionService。
Spring将自动识别出IOC容器中的ConversionService,并在Bean属性配置及Spring mvc处理方法入参绑定等场合使用它进行数据的转换
可通过ConversionServiceFactoryBean的converters属性注册自定义的类型转换器
转换器接口
spring定义了3中类型的转换器接口,实现任意一个转换器接口可以作为自定义转换器注册到ConversionServiceFactoryBean中:
- Converter
:将S类型对象转为T类型对象 - ConverterFactory:将相同系列多个“同质”Converter封装在一起。如果希望将一种类型的对象转换为另一种类型及其子类的对象(例如将String转换为Number及其子类(Integer、Long、Double)对象)可以使用转换器工厂类
- GenericConverter:将会根据类对象及目标类对象所在的宿主类中的上下文信息进行类型转换
2、mvc:annotaion-driven配置
还将提供以下支持:
-支持使用ConversionService实例对表单参数进行类型转换
-支持使用@NumberFormat annotation、
@DateTimeFormat注解完成数据类型的格式化
-支持使用@Valid 注解对JavaBean实例进行JSR303验证
-支持使用@RequestBody和@ResponseBody 注解
3、@InitBinder
由@InitBinder标识的方法,可以对WebDataBinder对象进行初始化。WebDataBinder是DataBinder的子类,用于完成表单字段到JavaBean属性的绑定
@InitBinder方法不能有返回值,它必须声明为void
@InitBinder方法的参数通常是WebDataBinder
@InitBinder
public void initBinder(WebDataBinder dataBinder){
xxx
}
4、类型转换
1、添加anntation-driven
2、bean属性添加注解:
@DataTimeFormate(pattern="yyyy-MM-dd")
@NumberFormat(pattern="#,###,###.#")
5、BindingResult
类型转换失败时,将失败结果返回到BindingResult,在handler方法可以添加参数BindingResult 获取进行处理
6、校验
JSR 303通过在Bean属性上标注类似@NotNull、@Max等标准指定校验规则,通过标准的验证接口对Bean进行验证。
实现:Hibernate Validator除了实现JSR 303标准,多了特定的注解
1)使用JSR 303标准
2)加入hibernate validator验证框架
3)在Spring mvc配置文件中添加
4)需要在bean的属性上添加对应的注解
5)在目标方法bean类型的前面添加@Valid注解
需要校验的Bean对象和其绑定结果对象或错误对象成对出现的,它们之间不允许什么其他的入参
@Valid Xxx x, BindingResult xx,@Valid Xxx x,BindingResult xxx
jsp显示错误消息,使用Jstl中的
错误消息国际化,添加国际化文件(文件内容格式:pattern.modleAttribute.属性名=xxx),添加国际化配置
六、json
添加@ResponseBody注解在方法上,为jackson包中的注解
json原理:添加json的HttpMessageConverter
七、国际化
1、思路
- 在页面上能够根据浏览器语言设置的情况对文本(不是内容),时间,数值进行本地化处理
2.可以在bean中获取国际化资源文件Locale对应的消息
3.可以通过超链接切换Locale,而不再依赖于浏览器的语言设置情况
2、解决:
1.使用JSTL的fmt标签
2.在bean中注入ResourceBundleMessageSource 的示例,使用其对应的 getMessage方法即可
3.配置LocalResolver和LocaleChangeInterceptor
八、文件上传
Spring MVC为文件上传提供了直接的支持,这种支持是通过即插即用的MultipartResolver实现的。Spring用Jakarta Commons FileUpload 技术实现了一个MultipartResolver实现类:
CommonsMultipartResovler
Spring MVC 上下文中默认没有装配 MultipdrtResovler,因此默认情况下不能处理文件的上传工作,如果想使用Spring的文件上传功能,需现在上下文中配置MultipartResolver
步骤
1)添加jar包:commons-fileupload、commos-io
2)配置MultipartResolver
<!--配置MultipartResolver-->
3)方法使用MultipartFile入参(文件下载使用ResponseEntity
4)多文件上传使用MultipartFile数值参数
九、拦截器
1、自定义拦截器
1)写拦截器:实现HandlerInterceptor接口
2)配置文件配置自定义拦截器
2、拦截器方法
1)preHandler
该方法在目标方法之前调用
如果返回true,继续调用后续的拦截器和目标方法
如果返回false,不会调用后续拦截器和目标方法
可以考虑做权限,日志,事务等
2)postHandle
调用目标方法之后,渲染视图之前
可以对请求域中的属性或视图做出修改
3)afterCompletion
渲染视图之后调用
释放资源
3、拦截器配置
可以配置拦截器(不)作用的路径mvc:mapping
4、拦截器顺序
十、异常处理
1、ExceptionHandlerExceptionResolver
ExceptionHandlerExceptionResolver的使用:@ExceptionHandle和@ControllerAdvice
@ExceptionHandle
方法添加@ExceptionHandle({})注解
1.在@ExceptionHandler方法的入参中可以加入Exception类型的参数,该参数即对应发生的异常对象
2.@ExceptionHandler 方法的入参中不能传入Map.若希望把异常信息传导页面上,需要使用ModelAndView作为返回值
3.@ExceptionHandler方法标记的异常有优先级的问题。
4.@ControllerAdvice:如果在当前 Handler中找不到@ExceptionHandler方法来出来当前方法出现的异常,则将去@ControllerAdvice 标记的类中查找@ExceptionHandler 标记的方法来处理异常。
@ControllerAdvice
在控制器类上添加注解@ControllerAdvice,可以将@ExceptionHandler集中写到此列中
@ExceptionHandler({RuntimeException.class})
public ModelAndView handleArithmeticException2(Exception ex){
System.out.println("[出异常了:"+ex);ModelAndView mv=new ModelAndView("error");mv.addObject("exception",ex);return mv;
}
2、ResponseStatusExceptionResolver
可以修改请求状态码,使用@ResponseStatus修饰类(Exception)或者修饰方法
Exception:错误时抛出,修改状态码
方法:无论方法成功与否,都会修改状态码
@ResponseStatus(value=HttpStatus.XXX,reason="")
3、DefaultHandlerExceptionResolver
对一些特殊的异常进行处理,比如:
NoSucnRequestHandlingMethodException、
HttpRequestMethodNotSupportedException、
HttpMediaTypeNotSupportedException等
4、SimpleMappingExceptionResolver
如果希望对所有异常进行统一处理,可以使用
SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常
error
十一、spring mvc运行原理
Handler:处理器,即含有目标方法的一系列信息
HandlerMapping:请求与处理器直接的映射
HandlerExecutionChain:处理器调用链,包含处理器和与处理器有关的拦截器
HandlerAdapter:处理器适配器,将处理器进行包装成一个适配器,进行各种操作
十二、spring mvc的IOC 和 spring的IOC
spring mvc的ioc容器中的bean可以来引用spring ioc容器中的bean,反之不行。即:Controller可以引用Server,但是Server不能引用Controller