SpringMVC学习笔记
准备工作
1.配置web.xml

(也可以设置不全拦截,加上这两句:
<mvc:default-servlet-handler/>
<mvc:annotation-driven></mvc:annotation-driven>
加上之后SpringMVC会对请求进行筛查,如果确实有对该映射的处理,就正常跳转,如果没有则由默认的 Servlet处理)
2.配置mvc的配置文件
2.1 配置自动扫描的包


2.2 配置视图解析器


(InternalResourceViewResolver是将方法返回的值和prefix和suffix拼接成实际的物理视图)


(BeanNameViewResolver:若方案的返回值是一个bean名(就是类名首字母小写),就会直接返回这个类的实例)
一. @RequestMapping
Spring MVC 使用 @RequestMapping 注解为控制器指定可以处理哪些 URL 请求
@RequestMapping可以在两个位置进行标注
-
类定义的上面:提供初步请求映射,相当与从根目录开始
-
方法的上面:进一步细分映射,若类定义处标注了@RequestMapping,则方法出标注的映射就是接着类之后的映射,若类没有标注,则相当与从根目录开始


(相当于处理URL为"/wbw/lzy"的请求)
@RequestMapping还可以加上请求方法条件

(他们之间是与关系,必须都满足才能对将请求映射到这个类或者这个方法上)二. 通过URL得到参数的几种方式
-
基本数据类型传递
SpringMVC会自动帮我们给参数注入值,这里只需要我们的参数名称和index.jsp里面input的name相同即可



-
@PathVariable
通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中 ,
详细来说:URL 中的 {xxx} 占位符可以通过@PathVariable("xxx") 绑定到操作方法的入参中。
例:url为"delete/123"

(则id=123)
-
@RequestParam
在处理方法入参处使用 @RequestParam 可以把请求参数传递给请求方法
– value:参数名
– required:是否必须。默认为 true, 表示请求参数中必须包含对应的参数,若不存在,将抛出异常
例:url为"handle5?username=wbw&age=20"


(则在方案中可以直接调用usernam和age,值为wbw和20)
三. Servlet原生的API可以作为Handle方法的参数,支持的类型包括
-
HttpServletRequest
-
HttpServletResponse
-
HttpSession
-
java.security.Principal
-
Locale
-
InputStream
-
OutputStream
-
Reader
-
Writer
例:


(可以在控制台输出:hello springmvc)
四. POJO
Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性(意思就是会根据请求参数自动给对象填充属性,但是必须保证请求参数名和属性名是一致的)
例:
有
一个表单:![]()
一个表单:
其jsp是:![]()

提交之后映射到这个
方法上
,springmvc会自动为user对象添加各个属性
方法上
,springmvc会自动为user对象添加各个属性
五. 处理模型数据
有ModleAndView和Map种选择
-
ModelAndView
当控制器处理完请求时,通常会将包含视图名称或视图对象以及一些模型属性ModelAndView对象返回到DispatcherServlet。(将数据输出到页面上换句话说就是把这个模型放到请求域里了)
作用:
1.返回到指定的页面
ModelAndView构造方法可以指定返回的页面名称
例:return new ModelAndView("redirect:/m07.jsp")
return new ModelAndView("hello");
通过setViewName()方法跳转到指定的页面
例:mav.setViewName("hello");
2.返回参数到指定页面的request作用于中
使用addObject()设置需要返回的值,addObject()有几个不同参数的方法,可以默认和指定返回对象的名字,参数会返回到新页面的request作用域中
@Controller
public class Test_ModelAndView {
@RequestMapping("Test_ModelAndView")
public ModelAndView test(){
ModelAndView mv=new ModelAndView();
//ModelAndView mv=new ModelAndView("welcome");//返回的文件名,和下一行一样的效果
mv.setViewName("welcome"); //返回的文件名
mv.addObject("message","hello kitty");
//类
User user = new User();
user.setAge(20);
user.setName("nihao");
mv.addObject("user",user);
//List
List<String> list = new ArrayList<String>();
list.add("java");
list.add("c++");
list.add("oracle");
mv.addObject("bookList", list);
//Map
Map<String,String> map = new HashMap<String,String>();
map.put("zhangsan", "北京");
map.put("lisi", "上海");
map.put("wangwu", "深圳");
mv.addObject("map",map);
return mv;
}
}
然后在jsp页面可以输出数据
welcom.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>Insert title here</title></head><body><body>
<!-- 输出普通字符 -->
${message } <br/>
<!-- 输出List -->
<p>书籍列表</p>
<c:forEach items="${bookList}" var="node">
<c:out value="${node}"></c:out>
</c:forEach>
<br/>
<br/>
${user }<br/>
<br/>
<table border="1">
<tr>
<th>Month</th>
<th>Savings</th>
</tr>
<tr>
<td>${user.name }</td>
<td>${user.age }</td>
</tr></table>
<br/>
<br/>
<!-- 输出Map -->
<c:forEach items="${map}" var="node">
姓名:<c:out value="${node.key}"></c:out>
住址:<c:out value="${node.value}"></c:out>
<br/>
</c:forEach>
</body>
</body></html>
输出的结果:
-
Map(Model,ModelMap)
——Spring MVC 在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器。
——如果方法的入参为 Map 或 Model 类型,Spring MVC 会将隐含模型的引用传递给这些入参。在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据
例:

(那么在jsp中写${requestScope.names}就可以在页面上显示[Tom,Jerry,Mike])
ModelAndView和Map区别?
答: ModelAndView的实例是需要我们手动new的,并且ModelAndView 可以自己寻址(因为setViemName方法设置了他指向的文件名),只需要return 返回其对象即可。而Map 的实例都是spirng mvc框架来自动创建并作为控制器方法参数传入,不用自己创建。需要return 返回指定的页面路径.
六. REST
浏览器 form 表单只支持 GET与 POST 请求,而DELETE、PUT 等 method 并不支持,Spring3.0 添加了一个过滤器,可以将这些请求转换为标准的 http 方法,使得支持 GET、POST、PUT 与DELETE 请求。
配置过程:
1.在web.xml文件中配置HiddenHttpMethodFilter,可将post请求转为put和delete
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
然后在

(发送post请求时携带一个name=_method的隐藏域,hiddenfilter会识别这个名字,并把其隐藏域对应的value值转为对应的请求方法发出去,这里发的就是put类型的请求)
七. ModelAttribute
@ModelAttribute最主要的作用是将数据添加到模型对象中(可用来完成从表单将数据传递给model对象的功能)
注:在方法定义上使用 @ModelAttribute 注解:Spring MVC在调用目标处理方法前,会先逐个调用在方法级上标注了@ModelAttribute 的方法。
运行流程:
1. 执行 @ModelAttribute 注解修饰的方法: 从数据库中取出对象, 把对象放入到了 Map 中. 键为: user
@ModelAttribute
public void getUser(@RequestParam(value="id",required=false) Integer id,
Map<String, Object> map){
System.out.println("modelAttribute method");
if(id != null){
//模拟从数据库中获取对象
User user = new User(1, "Tom", "123456");
System.out.println("从数据库中获取一个对象: " + user);
map.put("user", user);
}
}
(原始数据:1 Tom 123456)
2. SpringMVC 从 Map 中取出 User 对象, 并把表单的请求参数赋给该 User 对象的对应属性.
(表单中输入了密码,输入值为56789)[方法是入参:在进行数据绑定之前,先到请求范围当中查找指key(POJO类的首字母小写)对应的value值对象,就是下面对应的user]
3. SpringMVC 把上述对象传入目标方法的参数.
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user){
System.out.println("修改: " + user);
return SUCCESS;
}
(输出数据:1 Tom 56789)
例2:

———————————————————————————————
* 源代码分析的流程
* 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 对象
*(简单来说attrName属性为名字,target属性为对应的值或者对象)
* 2). SpringMVC 把表单的请求参数赋给了 WebDataBinder 的 target 对应的属性.
*(会用表单传来的值对原来的target属性对应的值进行更新)
* 3). *SpringMVC 会把 WebDataBinder 的 attrName 和 target 给到 implicitModel.
* 近而传到 request 域对象中.
* 4). 把 WebDataBinder 的 target 作为参数传递给目标方法的入参.
———————————————————————————————
八. 重定向和转发
-
一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理
-
如果返回的字符串中带 forward: 或者 redirect: 前缀时,SpringMVC 会对他们进行特殊处理:将 forward: 和redirect: 当成指示符,其后的字符串作为 URL 来处理
例:
– redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作
– forward:success.jsp:会完成一个到 success.jsp 的转发操作
九. mvc:view-controller
九. <mvc:annotation-driven/>
配置mvc:annotation-driven就是开启了注解驱动,Spring知道了我们开启了注解驱动后就可以通过context:component-scan/标签的配置,会自动为我们将扫描到的@Component,@Controller,@Service,@Repository等注解标记的组件注册到工厂中,来处理我们的请求。
他其中的一些标签:
-
<mvc:default-servlet-handler />
如果不设置这个标签,所有URL请求都将被Spring MVC的DispatcherServlet截获。设置了这个标签之后他会对URL进行筛查:
静态资源的请求→转由Web应用服务器默认的Servlet处理
不是静态资源的请求→才由DispatcherServlet继续处理。
-
<mvc:view-controller />
还是上面的问题,如果希望发送的请求不通过controller,直接跳转到目标页面,可以设置这个标签
例:
<mvc:view-controller path="/hello" view-name="123"></mvc:view-controller>
—path=”/hello” 就是你访问的路径(相当于RequestMapping(“/hello”))
—view-name=”hello”是你所要的视图(如123.jsp,相当于return “123”) 配置了这个后对于/hello请求,就会直接交给dispatcherServlet,然后使用ViewResolver进行解析。
相当有代码:
@RequestMapping(value="/hello")
public String hello(){
System.out.println("hello");
return "hello";
}
还可以配置重定向和转发
<mvc:view-controller path="/index" view-name="redirect:hello"></mvc:view-controller>
相当于
@RequestMapping("/index")
public String index(){
return "redirect:hello";
}
-
数据格式化(配置<mvc:annotation-driven/>就可以)
1.日期格式化 @DateTimeFormat
@DateTimeFormat(pattern = "yyyy-MM-dd") //这就是格式化,当输入字符串为(yyyy-MM-dd)类型的时候就会自动转化为Date类型:
private Date birthday;
pattern属性(必须):类型为字符串,指定解析/格式化字段数据的模式
2.数字类型格式化 @NumberFormat
@NumberFormat(pattern = "#,###,###.##") //这个就是一个通用式了,无论多少数字都可以转为double类型
private double money;
pattern属性(必须):类型为字符串
-
@Vaild——数据校验
只要在 Spring 容器中定义了一个LocalValidatorFactoryBean,即可将其注入到需要数据校验的 Bean 中。
<mvc:annotation-driven/> 会默认装配好一个LocalValidatorFactoryBean
所以想实现校验需要:
1.在处理方法的入参上标注 @valid 注解即可让 Spring MVC 在完成数据绑定后执行数据校验的工作
2.在bean的需要检验的属性上标注注解
——————————————————————————————————
注解包括:

——————————————————————————————————
例:
public class User implements Serializable {
@NotNull(message = "uid不能为空")
@Min(value = 1, message = "pid必须为正整数")
private Long uid;
@NotBlank(message = "userName不能为空")
private String userName;
@NotBlank(message = "address 不能为空")
private String address;
// getter/setter
}
@RequestMapping("/user/saveUser")
public String saveUser(@Valid User user, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
// 打印全部的错误信息
for (ObjectError error : bindingResult.getAllErrors()) {
System.out.println(error.getDefaultMessage());
}
}
// 返回第一条的错误信息
if (bindingResult.hasErrors()) {
String msg=bindingResult.getAllErrors().get(0).getDefaultMessage();
return msg;
}
}
并且,校验的结果会被保存在被校验入参对象(上文对应的是user)之后的 BindingResult 或Errors 入参中(需校验的 Bean 对象和其绑定结果对象或错误对象时成对出现的,它们之间不允许声明其他的入参)
— Errors 接口提供了获取错误信息的方法,如 getErrorCount() 或getFieldErrors(String field)
—BindingResult 扩展了 Errors 接口
其常用方法:
-getAllErrors(返回的是error数组)
-getDefaultMessage()(返回的是设置的错误提示信息)
错误信息不仅可以存在Error或BindingResult对象中,还会保存到“隐含模型”,隐含模型会暴露给JSP,所以在JSP中可以获取错误信息
通过: <form:errors path=“xxx”>显示错误消息
例:


作为码农中的一员,需要不断的学习,我学习之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。
本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。

浙公网安备 33010602011771号