SpringMVC笔记
Posted _如此甚好
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringMVC笔记相关的知识,希望对你有一定的参考价值。
导入SpringMVC只需要加入jar包就行了。
@PathVariable("xxx") 绑定到操作方法的入参中。
HttpMessageConverter<T> :
自定义拦截器:
然后在web.xml文件里配置一下DispatcherServlet,设置下需要拦截的URL即可。
<!-- 配置 SpringMVC 的 DispatcherServlet -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
一些必要的SpringMVC文件配置:
<!-- 配置自动扫描的包 -->
<context:component-scan base-package="com.atguigu.springmvc"></context:component-scan>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
有多种视图解析器: 待补
视图解析器详解:
试图解析的流程:
不管目标方法返回的是什么类型是String、ModelAndView还是View都,SpringMVC都会把它转换为ModelAndView类型,
然后通过视图解析器得到真正的物理视图,一个View对象,然后调用renderview得到响应结果。
InternalResourceViewResolver是支持InternalResourceView的视图解析器
InternalResourceViewResolver
• JSP 是最常见的视图技术,可以使用
InternalResourceViewResolver 作为视图解析器:
自定义视图:
自定义视图继承自View,完成getContentType方法(返回内容类型),和render方法(渲染视图)
@Component
public class HelloView implements View{
@Override
public String getContentType() {
return "text/html";
}
@Override
public void render(Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
response.getWriter().print("hello view, time: " + new Date());
}
}
然后在SpringMVC里配置
<!-- 配置视图 BeanNameViewResolver 解析器: 使用视图的名字来解析视图 -->
<!-- 通过 order 属性来定义视图解析器的优先级, order 值越小优先级越高 -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="100"></property>
</bean>
然后handler直接返回helloview的view名字,因为此时BeanNameViewResolver的优先级比较高所以先由这个视图解析器解析。
@RequestMapping("/testView")
public String testView(){
System.out.println("testView");
return "helloView";
}
待补。。。
default-servlet-handler 将在 SpringMVC 上下文中定义一个 DefaultServletHttpRequestHandler,
它会对进入 DispatcherServlet 的请求进行筛查, 如果发现是没有经过映射的请求, 就将该请求交由 WEB 应用服务器默认的
Servlet 处理. 如果不是静态资源的请求,才由 DispatcherServlet 继续处理
- 一般 WEB 应用服务器默认的 Servlet 的名称都是 default.
若所使用的 WEB 服务器的默认 Servlet 名称不是 default,则需要通过 default-servlet-name 属性显式指定
<mvc:default-servlet-handler/>
<mvc:annotation-driven></mvc:annotation-driven>
这个一般都是必加的。他的加入可以防止RequestMapping不会失效
• <mvc:annotation-driven /> 会自动注
册RequestMappingHandlerMapping、RequestMappingHandlerAdapter 与
ExceptionHandlerExceptionResolver 三个bean。• 还将提供以下支持:
– 支持使用 ConversionService 实例对表单参数进行类型转换
– 支持使用 @NumberFormat annotation、@DateTimeFormat
注解完成数据类型的格式化– 支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证
– 支持使用 @RequestBody 和 @ResponseBody 注解
SpringMVC的常用注解:
@Controller
标记目标方法类。这个类将为请求处理器
@RequestMapping
注解为控制器指定可以处理哪些URL请求
—类定义处:提供初步的请求映射信息。相对于 WEB 应用的根目录
—方法处:提供进一步的细分映射信息。相对于类定义处的 URL。若
类定义处未标注 @RequestMapping,则方法处标记的 URL 相对于
WEB 应用的根目录
• @RequestMapping 除了可以使用请求 URL 映射请求外,
还可以使用请求方法、请求参数及请求头映射请求 • @RequestMapping 的 value、method、params 及 heads
分别表示请求 URL、请求方法、请求参数及请求头的映射条
件,他们之间是与的关系,联合使用多个条件可让请求映射
更加精确化。
分别表示请求 URL、请求方法、请求参数及请求头的映射条
件,他们之间是与的关系,联合使用多个条件可让请求映射
更加精确化。
列如:
• 通过 @PathVariable 可以将 URL 中占位符参数绑定到控
制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable("xxx") 绑定到操作方法的入参中。
例如:
@RequestMapping("/delete/{id}")
public String delete(@PathVariable("id") Interger id){
...
}
@RequestParam
将URL中的请求参数的值传递给请求方法
– value:参数名
– required:是否必须。默认为 true, 表示请求参数中必须包含对应
的参数,若不存在,将抛出异常
例如:
@RequestMapping("/xxx")
public String delete(@RequestParam(value="userName",required=false) String userName,
@RequestParam("age") int age){
...
}
这种类似的有
@RequestHeader
@CookieValue
public String handle(@CookieValue(value="sessionId",required=false) String
sessionID)
就不详细介绍了
Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性。
如:dept.deptId、dept.address.tel 等
@ModelAndView
控制器处理方法的返回值如果为 ModelAndView, 则其既
包含视图信息,也包含模型数据信息。
Spring MVC 在调用方法前会创建一个隐
含的模型对象作为模型数据的存储容器。– 如果方法的入参为 Map 或 Model 类
型,Spring MVC 会将隐含模型的引用传- 递给这些入参。在方法体内,开发者可以通过这个入参对象访问到模型中的所有数
据,也可以向模型中添加新的属性数据.
在方法定义上使用 @ModelAttribute 注解:Spring MVC
在调用目标处理方法前,会先逐个调用在方法级上标注了@ModelAttribute 的方法
/**
* 运行流程:
* 1. 执行 @ModelAttribute 注解修饰的方法: 从数据库中取出对象, 把对象放入到了 Map 中. 键为: user
* 2. SpringMVC 从 Map 中取出 User 对象, 并把表单的请求参数赋给该 User 对象的对应属性.
* 3. SpringMVC 把上述对象传入目标方法的参数.
*
* 注意: 在 @ModelAttribute 修饰的方法中, 放入到 Map 时的键需要和目标方法入参类型的第一个字母小写的字符串一致!
*
* SpringMVC 确定目标方法 POJO 类型入参的过程
* 1. 确定一个 key:
* 1). 若目标方法的 POJO 类型的参数木有使用 @ModelAttribute 作为修饰, 则 key 为 POJO 类名第一个字母的小写
* 2). 若使用了 @ModelAttribute 来修饰, 则 key 为 @ModelAttribute 注解的 value 属性值.
* 2. 在 implicitModel 中查找 key 对应的对象, 若存在, 则作为入参传入
* 1). 若在 @ModelAttribute 标记的方法中在 Map 中保存过, 且 key 和 1 确定的 key 一致, 则会获取到.
* 3. 若 implicitModel 中不存在 key 对应的对象, 则检查当前的 Handler 是否使用 @SessionAttributes 注解修饰,
* 若使用了该注解, 且 @SessionAttributes 注解的 value 属性值中包含了 key, 则会从 HttpSession 中来获取 key 所
* 对应的 value 值, 若存在则直接传入到目标方法的入参中. 若不存在则将抛出异常.
* 4. 若 Handler 没有标识 @SessionAttributes 注解或 @SessionAttributes 注解的 value 值中不包含 key, 则
* 会通过反射来创建 POJO 类型的参数, 传入为目标方法的参数
* 5. SpringMVC 会把 key 和 POJO 类型的对象保存到 implicitModel 中, 进而会保存到 request 中.
*
* 源代码分析的流程
* 1. 调用 @ModelAttribute 注解修饰的方法. 实际上把 @ModelAttribute 方法中 Map 中的数据放在了 implicitModel 中.
* 2. 解析请求处理器的目标参数, 实际上该目标参数来自于 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 给到 implicitModel.
* 近而传到 request 域对象中.
* 4). 把 WebDataBinder 的 target 作为参数传递给目标方法的入参.
*/
@SessionAttributes
/**
* @SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外(实际上使用的是 value 属性值),
* 还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(实际上使用的是 types 属性值)
*
* 注意: 该注解只能放在类的上面. 而不能修饰放方法.
*/
数据绑定流程 :
• 1. Spring MVC 主框架将 ServletRequest 对象及目标方
法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象
• 2. DataBinder 调用装配在 Spring MVC 上下文中的
ConversionService 组件进行数据类型转换、数据格式化工作。将 Servlet 中的请求信息填充到入参对象中
• 3. 调用 Validator 组件对已经绑定了请求消息的入参对象
进行数据合法性校验,并最终生成数据绑定结果BindingData 对象
• 4. Spring MVC 抽取 BindingResult 中的入参对象和校验
错误对象,将它们赋给处理方法的响应入参其运行流程如下图所示:
数据格式化:
<mvc:annotation-driven/> 默认创建的ConversionService 实例即为
FormattingConversionServiceFactroyBean
• FormattingConversionServiceFactroyBean 内部已经注册了 :
– NumberFormatAnnotationFormatterFactroy:支持对数字类型的属性
使用 @NumberFormat 注解
– JodaDateTimeFormatAnnotationFormatterFactroy:支持对日期类型
的属性使用 @DateTimeFormat 注解
例如:
@DateTimeFormat(pattern="yyyy/MM/dd")
private Date birthday;
@NumberFormat(pattern="#,###.##")
自定义类型转换器
待补。。。。
@InitBinder
• 由 @InitBinder 标识的方法,可以对 WebDataBinder 对
象进行初始化。WebDataBinder 是 DataBinder 的子类,用于完成由表单字段到 JavaBean 属性的绑定• @InitBinder方法不能有返回值,它必须声明为void。
• @InitBinder方法的参数通常是是 WebDataBinder
例如:
@InitBinder
public void initBinder(WebDataBinder dataBinder){
dataBinder.setDisallowedFields("xxx");
}
HttpMessageConverter<T> :
负责将请求信息转换为一个对象(类型为 T),将对象(类型为 T)输出为响应信息
其中HttpInputMessage就是输入流
HttpOutputMessage就是输出流
如图所示,通俗的讲,就是将输入流变成java对象,把java对象变成输出流。
使用以下2个注解即可使用HttpMessageConverter
-- @ResponseBody
-- @RequsetBody
@ResponseBody
@RequestMapping("/testHttpMessageConverter")
public String testHttpMessageConverter(@RequestBody String body){
System.out.println(body);
return "helloworld! " + new Date();
}
文件上传:
查看视频即可,很简单。
自定义拦截器:
接口继承自HandlerInterceptor,实现其抽象方法
需要在springmvc.xml文件里进行配置: 具体配置如下所示
<mvc:interceptors>
<!-- 配置自定义的拦截器 -->
<bean class="com.atguigu.springmvc.interceptors.FirstInterceptor"></bean>
<!-- 配置拦截器(不)作用的路径 -->
<mvc:interceptor>
<mvc:mapping path="/emps"/>
<bean class="com.atguigu.springmvc.interceptors.SecondInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
其中要实现的3个接口如下
/**
* 该方法在目标方法之前被调用.
* 若返回值为 true, 则继续调用后续的拦截器和目标方法.
* 若返回值为 false, 则不会再调用后续的拦截器和目标方法.
*
* 可以考虑做权限. 日志, 事务等.
*/
@Override
以上是关于SpringMVC笔记的主要内容,如果未能解决你的问题,请参考以下文章
学习笔记——SpringMVC处理响应数据;SpringMVC处理请求域响应乱码问题
SpringMVC笔记- 不配置HandlerMapping