一.建立SpringMVC步骤
1.配置Maven的依赖或导jar包
2.在 web.xml 中配置 DispatcherServlet并加入 Spring MVC 的配置文件
<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>
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
3.编写处理请求的处理器,并标识为处理器
<!--配置自动扫描-->
<context:component-scan base-package="com.itlc.springmvc"/>
4.编写视图
<!--配置视图解析器:如何把handler方法返回值解析为实际的物理视图-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
二.使用 @RequestMapping 映射请求
1.类加入容器,加@Controller
2.@RequestMapping作用点
– 类定义处:提供初步的请求映射信息。相对于 WEB 应用的根目录
– 方法处:提供进一步的细分映射信息。相对于类定义处的 URL。若
类定义处未标注 @RequestMapping,则方法处标记的 URL 相对于
WEB 应用的根目录
@RequestMapping("/testMethod")
public String testMethod(){
System.out.println("testMethod");
return SUCCESS;
}
3. @RequestMapping 修饰其他的
除了可以使用请求 URL 映射请求外,
还可以使用请求方法、请求参数及请求头映射请求
@RequestMapping 的 value、method、params 及 heads
分别表示请求 URL、请求方法、请求参数及请求头的映射条
件,他们之间是与的关系,联合使用多个条件可让请求映射
更加精确化。
params 和 headers支持简单的表达式:
– param1: 表示请求必须包含名为 param1 的请求参数
– !param1: 表示请求不能包含名为 param1 的请求参数
– param1 != value1: 表示请求包含名为 param1 的请求参数,但其值
不能为 value1
– {“param1=value1”, “param2”}: 请求必须包含名为 param1 和param2
的两个请求参数,且 param1 参数的值必须为 value1
Ant 风格资源地址支持 3 种匹配符:
?:匹配文件名中的一个字符
*:匹配文件名中的任意字符
**:** 匹配多层路径
@RequestMapping("/testRequestMapping")
public String testRequestMapping(){
System.out.println("testRequestMapping");
return SUCCESS;
}
/*
@PathVariable 可以用来映射URL中的占位符到目标方法的参数中
@param id
*/
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id){
System.out.println("testPathVariable: "+id);
return SUCCESS;
}
4.REST
– /order/1 HTTP GET :得到 id = 1 的 order
– /order/1 HTTP DELETE:删除 id = 1的 order
– /order/1 HTTP PUT:更新id = 1的 order
– /order HTTP POST:新增 order
HiddenHttpMethodFilter:浏览器 form 表单只支持 GET
与 POST 请求,而DELETE、PUT 等 method 并不支
持,Spring3.0 添加了一个过滤器,可以将这些请求转换
为标准的 http 方法,使得支持 GET、POST、PUT 与
DELETE 请求
过滤器:
<!--配置org.springframework.web.filter.HiddenHttpMethodFilter:可以把POST请求
转化为DELETE或POST请求-->
<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>
处理器:
@RequestMapping(value = "/testRest/{id}", method = RequestMethod.PUT)
public String testRestPut(@PathVariable Integer id) {
System.out.println("testRest Put: " + id);
return SUCCESS;
}
@RequestMapping(value = "/testRest/{id}", method = RequestMethod.DELETE)
public String testRestDelete(@PathVariable Integer id) {
System.out.println("testRest Delete: " + id);
return SUCCESS;
}
@RequestMapping(value = "/testRest", method = RequestMethod.POST)
public String testRest() {
System.out.println("testRest POST");
return SUCCESS;
}
@RequestMapping(value = "/testRest/{id}", method = RequestMethod.GET)
public String testRest(@PathVariable Integer id) {
System.out.println("testRest GET: " + id);
return SUCCESS;
}
三.映射请求参数 & 请求参数
Spring MVC 通过分析处理方法的签名,将 HTTP 请求信
息绑定到处理方法的相应人参中。
• Spring MVC 对控制器处理方法签名的限制是很宽松的,
几乎可以按喜欢的任何方式对方法进行签名。
• 必要时可以对方法及方法入参标注相应的注解(
@PathVariable
、@RequestParam、@RequestHeader 等)、Spring
MVC 框架会将 HTTP 请求的信息绑定到相应的方法入参
中,并根据方法的返回值类型做出相应的后续处理。
1.@RequestParam
@RequestParam来映射请求参数,处理表单value 值即请求参数的参数名
,required表示该参数是否必须,默认为truedefaultValue请求参数的默认值
public String testRequestParam(@RequestParam(value = "username") String un,
@RequestParam(value = "age",required = false,defaultValue = "0") int age){
System.out.println("testRequestParam,username"+un+",age:"+age);
return SUCCESS;
}
2.@RequestHeader(了解)
@RequestHeader来映射请求消息头
用法同@RequestParam
@RequestMapping("/testRequestHeader")
public String testRequestHeader(@RequestHeader(value = "Accept-Language") String al){
System.out.println("testRequestHeader:Accept-Language"+al);
return SUCCESS;
}
3.@CookieValue(了解)
@CookieValue来映射cookie
用法同@RequestParam
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String js){
System.out.println("testCookieValue: sessionId:"+js);
return SUCCESS;
}
4.pojo
表格提交利用类结合表单,直接得到对象,允许多级联动
@RequestMapping("/testPojo")
public String testPojo(User user){
System.out.println("testPojo:"+user);
return SUCCESS;
}
表单:
<form action="springmvc/testPojo" method="POST">
用户名:<input type="text" name="userName"/><br/>
密码:<input type="password" name="password"/><br/>
邮箱:<input type="text" name="email"/><br/>
年龄:<input type="text" name="age"/><br/>
省份 <input type="text" name="address.province"/><br/>
城市:<input type="text" name="address.city"/><br/>
<input type="submit" value="Submit"/><br/>
</form>
User类:
package com.itlc.springmvc.entities;
public class User {
private int id;
private String userName;
private String passWord;
private String email;
private int age;
private Address address;
@Override
public String toString() {
return "User{" + "id=" + id + ", userName='" + userName + '\'' + ", passWord='" + passWord + '\'' + ", email='" + email + '\'' + ", age=" + age + ", address=" + address + '}';
}
public User(){}
public String getUserName() {
return userName;
}
public User setUserName(String userName) {
this.userName = userName;
return this;
}
public String getPassWord() {
return passWord;
}
public User setPassWord(String passWord) {
this.passWord = passWord;
return this;
}
public String getEmail() {
return email;
}
public User setEmail(String email) {
this.email = email;
return this;
}
public int getAge() {
return age;
}
public User setAge(int age) {
this.age = age;
return this;
}
public Address getAddress() {
return address;
}
public User(int id, String userName, String passWord, String email, int age, Address address) {
this.id = id;
this.userName = userName;
this.passWord = passWord;
this.email = email;
this.age = age;
this.address = address;
}
public int getId() {
return id;
}
public User setId(int id) {
this.id = id;
return this;
}
public User setAddress(Address address) {
this.address = address;
return this;
}
}
5.API作为目标参数
可以使用Servlet原生的API作为目标参数,可以支持以下的 ServletAPI 类型的参数
HttpServletRequest
HttpServletResponse
HttpSession
java.security.Principal
Locale
InputStream
OutputStream
Reader
Writer
@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request, HttpServletResponse response){
System.out.println("testServletAPI,"+request+","+response);
return SUCCESS;
}
四.处理模型数据
Spring MVC 提供了以下几种途径输出模型数据:
– ModelAndView: 处理方法返回值类型为 ModelAndView
时, 方法体即可通过该对象添加模型数据
– Map 及 Model: 入参为
org.springframework.ui.Model、org.springframework.ui.
ModelMap 或 java.uti.Map 时,处理方法返回时,Map
中的数据会自动添加到模型中。
– @SessionAttributes: 将模型中的某个属性暂存到
HttpSession 中,以便多个请求之间可以共享这个属性
– @ModelAttribute: 方法入参标注该注解后, 入参的对象
就会放到数据模型中
1. ModelAndView
目标方法的返回值可以是ModelAndView类型
其中包括视图和模型信息
springMVC会把ModelAndView的model中数据放入到request对象中
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
String viewName=SUCCESS;
ModelAndView modelAndView=new ModelAndView(viewName);
//添加模型数据到ModelAndview
modelAndView.addObject("time",new Date());
return modelAndView;
}
2. Map类型
目标方法可以添加Map类型(也可以是Model或者ModelMap类型)的参数
@RequestMapping("/testMap")
public String testMap(Map<String,Object> map){
map.put("names", Arrays.asList("Tom","Jerry","Mike"));
return SUCCESS;
}
3.SessionAttributes
@SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外(使用value属性值),
还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(使用type属性值)
注意:该注解只能放在类的上面,不能放在方法上边
4.@ModelAttribute
当有@ModelAttribute标记的方法时的执行步骤:
1.执行有@ModelAttribute注解标记的方法:从数据库中取出对象,把对象放到Map中,键为user
2.springMVC从Map中取出User对象,并把表单中的请求参数赋给User对象的对应属性
3.springMVC把上述对象传入目标方法的参数
注意:在@ModelAttribute注解标记的方法中,放入Map时的键需要和目标方法参数类型的第一个
字母小写的字符串一致
SpringMVC确定目标方法POJO类型入参的过程
1.确定一个key:
若目标方法的POJO属性使用了@ModelAttribute来修饰,则attrName值即为
@ModelAttribute的value属性值
2.在implicitModel中查找key对应的对象,若存在,则作为入参传入
若在@ModelAttribute标记的方法中在Map中保存过,且key和确定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中的数据
放在了limplicitModel中。
2.解析请求处理器的目标参数,实际上该目标参数来自于WebDataBinder对象的target属性
(1)创建WebDataBinder对象:
1)确定objectName属性:若传入的attrName属性值为""。则objectName为类名第一个字母小写
注意:attrName,若目标方法的POJO属性使用了@ModelAttribute来修饰,则attrName值即
为@ModelAttribute的value属性值
(2)确定target属性:
>在implicitModel中查找attrName对应的属性值,若存在,ok
>*若不存在:则验证当前的Handler中是否使用了@SessionAttributes进行修饰,若使用了,
则尝试从Session中获取对应的attrName所对应的属性值。若session中没有对应的属性值
则抛出了异常
>若Handler没有使用@SessionAttributes进行修饰,或@SessionAttributes中没有使用
value值指定的key和attrName相匹配,则通过反射创建了POJO对象
3.SpringMVC把表单中的请求参数赋给了WebDataBinder的target对应的属性
4.*SpringMVC会把WebDataBinder的attrName和target给到limplicitModel,进而传到request域中
5.把WebDataBinder的target作为参数传递给目标方法的入参
@RequestMapping("/testModelAttribute")
public String testModelAttribute(@ModelAttribute(value = "kk") User user){
System.out.println("修改:"+user);
return SUCCESS;
}
1.有@ModelAttribute标记的方法,会在每个目标方法执行之前被springMVC调用
2.@ModelAttribute注解也可以来修饰目标方法POJO类型的入参,其value属性值有如下的作用:
(1)SpringMVC会使用value属性值在implicitModel中查找对应的对象,若存在则会直接
传入到目标方法入参中
(2)SpringMVC会以value为key,POJO类型的对象为value,存入到request中
@ModelAttribute
public void getUser(@RequestParam(value = "id",required = false) Integer id,Map<String,Object> map){
if (id!=null){
/*模拟获得*/
User user=new User(1,"tom","123456","[email protected]",12,new Address("1","2"));
System.out.println("从数据库获得一个对象"+user);
map.put("kk",user);
}
}
五.视图和视图解析器
请求处理方法执行完成后,最终返回一个 ModelAndView
对象。对于那些返回 String,View 或 ModeMap 等类型的
处理方法,Spring MVC 也会在内部将它们装配成一个
ModelAndView 对象,它包含了逻辑名和模型对象的视图
• Spring MVC 借助视图解析器(ViewResolver)得到最终
的视图对象(View),最终的视图可以是 JSP ,也可能是
Excel、JFreeChart 等各种表现形式的视图
1.配置国际化资源文件
<!--配置国际化资源文件-->
<bean id="MessageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"/>
</bean>
2.自定义视图
<!--配置自定义视图BeanNameViewResolver解析器:使用视图的名字来解析视图-->
<!--通过order属性来定义视图解析器的优先级,order值越小优先级越高-->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="100"/>
</bean>
自定义视图类实现View接口并添加@Component标签,放入容器中
@Component
public class HelloView implements View{
@Override
public String getContentType() {
return "text/html";
}
@Override
public void render(Map<String, ?> map, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
httpServletResponse.getWriter().print("hello view,time:"+new Date());
}
}
则调用该处理器时会调用自定义视图中的render方法
@RequestMapping("/helloView")
public String testView(){
System.out.println("helloView");
return "helloView";
}
3.请求转发
请求转发和重定向,如果返回的字符串中带 forward: 或 redirect: 前缀
时,SpringMVC 会对他们进行特殊处理:将 forward: 和
redirect: 当成指示符,其后的字符串作为 URL 来处理
– redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作
– forward:success.jsp:会完成一个到 success.jsp 的转发操作
@RequestMapping("/testRedirect")
public String testRedirect(){
System.out.println("testRedirect");
return "redirect:/index.jsp";
}