SpringMVC从入门到精通(终结版)

来源:互联网 发布:郝斌c语言不压缩百度云 编辑:程序博客网 时间:2024/05/01 20:20

1、项目配置文件

1.1、pom.xml文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.somnus</groupId>    <artifactId>SpringMVC</artifactId>    <packaging>war</packaging>    <version>0.0.1-SNAPSHOT</version>    <properties>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>    </properties>    <!-- 指定Maven仓库 -->    <repositories>        <!-- oschina的maven仓库 -->        <repository>            <id>oschinaRepository</id>            <name>local private nexus</name>            <url>http://maven.wozsz.com/content/groups/public/</url>            <releases>                <enabled>true</enabled>            </releases>            <snapshots>                <enabled>true</enabled>            </snapshots>        </repository>    </repositories>    <dependencies>        <!-- servlet & jsp -->        <dependency>            <groupId>javax.servlet</groupId>            <artifactId>servlet-api</artifactId>            <version>2.5</version>            <scope>provided</scope>        </dependency>        <dependency>            <groupId>javax.servlet</groupId>            <artifactId>jstl</artifactId>            <version>1.2</version>        </dependency>        <dependency>            <groupId>javax.servlet.jsp</groupId>            <artifactId>jsp-api</artifactId>            <version>2.2</version>            <scope>provided</scope>        </dependency>        <!-- 加入springmvc依赖包 -->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-webmvc</artifactId>            <version>3.2.5.RELEASE</version>        </dependency>        <!-- 加入fileupload依赖包 -->        <dependency>            <groupId>commons-fileupload</groupId>            <artifactId>commons-fileupload</artifactId>            <version>1.3.1</version>        </dependency>        <!-- bean validator -->        <dependency>            <groupId>org.hibernate</groupId>            <artifactId>hibernate-validator</artifactId>            <version>4.3.2.Final</version>        </dependency>    </dependencies>    <build>        <finalName>SpringMVC</finalName>        <plugins>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-compiler-plugin</artifactId>                <configuration>                    <target>1.7</target>                    <resource>1.7</resource>                    <encoding>${project.build.sourceEncoding}</encoding>                </configuration>            </plugin>        </plugins>    </build></project>

文件中所添加的每个依赖jar包都有自己的作用,后面再谈到相关知识点时会点出。

1.2、web.xml文件

<?xml version="1.0" encoding="UTF-8"?><web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee     http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">    <display-name>SpringMVC</display-name>    <welcome-file-list>        <welcome-file>index.jsp</welcome-file>    </welcome-file-list>    <filter>        <filter-name>characterEncodingFilter</filter-name>        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>        <init-param>            <param-name>encoding</param-name>            <param-value>UTF-8</param-value>        </init-param>        <init-param>            <param-name>forceEncoding</param-name>            <param-value>true</param-value>          </init-param>    </filter>    <filter-mapping>        <filter-name>characterEncodingFilter</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping>    <servlet>        <servlet-name>spring</servlet-name>        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>        <load-on-startup>1</load-on-startup>    </servlet>    <servlet-mapping>        <servlet-name>spring</servlet-name>        <url-pattern>/</url-pattern>    </servlet-mapping></web-app>

我们在学SpringMVC的时候都知道,它需要一个spring配置文件,用来初始化SpringMVC子容器,既可以指定也可以不指定文件位置。

如果不指定,如上面所配置,那么org.springframework.web.servlet.DispatcherServlet会从默认位置(/WEB-INF/[servlet-name]-servlet.xml)加载,也就是/WEB-INF/spring-servlet.xml

如果需要指定呢,比如需要把spring配置文件放在src/main/resources中呢,如下图
这里写图片描述

配置方式如下:

<servlet>    <servlet-name>spring</servlet-name>    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    <init-param>          <param-name>contextConfigLocation</param-name>          <param-value>classpath:/spring-mvc.xml</param-value>      </init-param>    <load-on-startup>1</load-on-startup></servlet>

谈到web.xml文件,说一个需要注意的一个细节,url-pattern需要映射的路径,经常会看到下面两种方式

方式一

<servlet-mapping>    <servlet-name>spring</servlet-name>    <url-pattern>/</url-pattern></servlet-mapping>

方式二

<servlet-mapping>    <servlet-name>dispatcher</servlet-name>    <url-pattern>*.html</url-pattern></servlet-mapping><servlet-mapping>    <servlet-name>dispatcher</servlet-name>    <url-pattern>*.action</url-pattern></servlet-mapping><servlet-mapping>    <servlet-name>dispatcher</servlet-name>   <url-pattern>*.do</url-pattern></servlet-mapping>

它们有什么区别呢,以及在开发中注意的地方

方式一:任意路径都会被映射,能够被org.springframework.web.servlet.DispatcherServlet处理

方式二:只有指定的路径才会被处理,如htmlactiondo结尾

两种方式其实任意一种都可以,但是使用方式二,静态资源文件(js、css、images、plugins、fonts)就不能放在WEB-INF里面,只能放在webapp里面,因为映射里没有包含静态文件的路径。方式一就没问题,但是需要在springmvc配置文件中做静态资源映射,1.3中会做介绍。

1.3、spring-servlet.xml配置文件

<?xml version="1.0" encoding="UTF-8" standalone="no"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xmlns:context="http://www.springframework.org/schema/context"    xmlns:mvc="http://www.springframework.org/schema/mvc"    xsi:schemaLocation="        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd         http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">    <!-- 启动注解驱动的Spring MVC功能,注册请求url和注解POJO类方法的映射-->    <mvc:annotation-driven />    <!-- 如果当前请求为"/"时,则转发到“/helloworld/index" -->    <mvc:view-controller path="/" view-name="forward:/helloworld/index"/>     <!-- 静态资源映射 -->    <mvc:resources mapping="/js/**" location="/WEB-INF/js/" />    <mvc:resources mapping="/css/**" location="/WEB-INF/css/" />    <mvc:resources mapping="/fonts/**" location="/WEB-INF/fonts/" />    <mvc:resources mapping="/plugins/**" location="/WEB-INF/plugins/" />    <mvc:resources mapping="images/**" location="/WEB-INF/images/" />    <!-- 当上面要访问的静态资源不包括在上面的配置中时,则根据此配置来访问 -->    <mvc:default-servlet-handler/>    <!-- 开启controller注解支持 -->    <!-- use-default-filters="false" 只扫描指定的注解 -->    <context:component-scan base-package="com.somnus.controller" use-default-filters="false">        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>    </context:component-scan>    <!-- 视图解析器 -->   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">       <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>       <property name="contentType" value="text/html"/>               <property name="prefix" value="/WEB-INF/views/"/>       <property name="suffix" value=".jsp"/>   </bean></beans>

开启注解映射支持,它是为了简化配置的缩写形式,它相当于以下2个配置:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/><bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

由于我们在web.xml文件里面配置的是拦截所有的请求到该servlet,所以我们在这里要对静态资源文件映射作一下配置,否则请求这些资源文件会返回404

<!-- 静态资源映射 -->  <mvc:resources mapping="/js/**" location="/WEB-INF/js/" />  <mvc:resources mapping="/css/**" location="/WEB-INF/css/" />  <mvc:resources mapping="/fonts/**" location="/WEB-INF/fonts/" />  <mvc:resources mapping="/plugins/**" location="/WEB-INF/plugins/" />  <mvc:resources mapping="images/**" location="/WEB-INF/images/" />  <!-- 当上面要访问的静态资源不包括在上面的配置中时,则根据此配置来访问 -->  <mvc:default-servlet-handler/>  

开启Controller注解支持,并配置只扫描指定包下面的Controller:

<context:component-scan base-package="com.demo.web.controllers" use-default-filters="false">      <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>  </context:component-scan> 

配置视图解析器,并指定视图所在的文件夹:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">     <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>     <property name="contentType" value="text/html"/>             <property name="prefix" value="/WEB-INF/views/"/>     <property name="suffix" value=".jsp"/>  </bean>  

2、简单的demo例子实现

添加HelloWorldController,在项目中新建一个web的Source Folder文件夹,并在文件夹下面添加com.somnus.web.controller包,在包中添加一个HelloWorldController类,类中内容如下:

package com.somnus.web.controller;  import org.springframework.stereotype.Controller;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RequestMethod;  import org.springframework.web.servlet.ModelAndView;  @Controller  @RequestMapping(value = "/helloworld")  public class HelloWorldController {      @RequestMapping(value="/index", method = {RequestMethod.GET})      public ModelAndView index(){          ModelAndView modelAndView = new ModelAndView();            modelAndView.addObject("message", "Hello World!");            modelAndView.setViewName("index");            return modelAndView;      }  }  

其中@Controller 注解把该class指定为controller,controller 上的@RequestMapping 注解的 value值指定该controller所映射的请求。

方法上的@RequestMapping 注解指定该方法为一个action,value 值指定该action所映射的请求,method 中的RequestMethod.GET指定该action只接受get请求。

ModelAndView 中的setViewName指定了该action所对应的视图名称,解析视图时会在spring-servlet.xml文件指定的视图文件夹中寻找对应的视图。

添加视图,在项目/WEB-INF文件夹下新建一个views文件夹,并在views中添加index.jsp视图,视图内容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!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>      ${message}  </body>  </html>  

运行项目,由于我们之前配置了: 所以直接可以看到结果:

这里写图片描述

把请求的URL地址改为配置的地址:http://localhost:8080/SpringMVC/helloworld/index,可以看到结果相同:

这里写图片描述

3、URL请求到Action的映射规则

3.1、URL路径映射

3.1.1、对一个action配置多个URL映射

我们把HelloWorldController的index() action方法的@RequestMapping更改为@RequestMapping(value={“/index”, “/hello”}, method = {RequestMethod.GET}),这表示对该action配置了/index和/hello两个映射。运行测试,如下:

http://localhost:8080/SpringMVC/helloworld/hello

这里写图片描述

可以看到/helloworld/hello请求也成功匹配

3.1.2、URL请求参数映射

这在查询的时候经常用到,比如我们根据id或编号来获取某一条记录。

在HelloWorldController添加一个getDetail的action,代码如下:

@RequestMapping(value="/detail/{id}", method = {RequestMethod.GET})  public ModelAndView getDetail(@PathVariable(value="id") Integer id){      ModelAndView modelAndView = new ModelAndView();        modelAndView.addObject("id", id);        modelAndView.setViewName("detail");        return modelAndView;  }  

其中value=”/detail/{id}“,中的{id}为占位符表示可以映射请求为/detail/xxxx 的URL如:/detail/123等。

方法的参数@PathVariable(value=”id”) Integer id 用于将URL中占位符所对应变量映射到参数id上,@PathVariable(value=”id”) 中value的值要和占位符/{id}大括号中的值一致。

在views中添加detail.jsp视图,用于将获取到的id值展示出来。视图内容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!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>      ${id}  </body>  </html>  

运行测试,请求URL地址 http://localhost:8080/SpringMVC/helloworld/detail/123 ,结果如下:

这里写图片描述

可以看到已经正确的显示了我们请求的id。

3.1.3、URL通配符映射

我们还可以通过通配符对URL映射进行配置,通配符有“?”和“”两个字符。其中“?”表示1个字符,“”表示匹配多个字符,“**”表示匹配0个或多个路径。

例如:

“/helloworld/index?”可以匹配“/helloworld/indexA”、“/helloworld/indexB”,但不能匹配“/helloworld/index”也不能匹配“/helloworld/indexAA”;“/helloworld/index*”可以匹配“/helloworld/index”、“/helloworld/indexA”、“/helloworld/indexAA”但不能匹配“/helloworld/index/A”;“/helloworld/index/*”可以匹配“/helloworld/index/”、“/helloworld/index/A”、“/helloworld/index/AA”、“/helloworld/index/AB”但不能匹配“/helloworld/index”、“/helloworld/index/A/B”;“/helloworld/index/**”可以匹配“/helloworld/index/”下的多有子路径,比如:“/helloworld/index/A/B/C/D”;

如果现在有“/helloworld/index”和“/helloworld/*”,如果请求地址为“/helloworld/index”那么将如何匹配?SpringMVC会按照最长匹配优先原则(即和映射配置中哪个匹配的最多)来匹配,所以会匹配“/helloworld/index”,下面来做测试:

在HelloWorldController添加一个urlTest的action,内容如下:

@RequestMapping(value="/*", method = {RequestMethod.GET})  public ModelAndView urlTest(){      ModelAndView modelAndView = new ModelAndView();         modelAndView.setViewName("urltest");        return modelAndView;  }  

在views文件夹中新加一个视图urltest.jsp,为了和index.jsp做区别urltest.jsp的内容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!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>      urlTest!  </body>  </html> 

3.1.4、URL正则表达式映射

Spring MVC还支持正则表达式方式的映射配置,我们通过一个测试来展示:

在HelloWorldController添加一个regUrlTest的action,内容如下:

@RequestMapping(value="/reg/{name:\\w+}-{age:\\d+}", method = {RequestMethod.GET})  public ModelAndView regUrlTest(@PathVariable(value="name") String name, @PathVariable(value="age") Integer age){      ModelAndView modelAndView = new ModelAndView();         modelAndView.addObject("name", name);       modelAndView.addObject("age", age);       modelAndView.setViewName("regurltest");        return modelAndView;  }  

在views文件夹中新加一个视图regurltest.jsp内容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!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>      ${name}-${age}  </body>  </html>  

请求http://localhost:8080/SpringMVC/helloworld/reg/Hanmeimei-18查看结果:

这里写图片描述

请求http://localhost:8080/SpringMVC/helloworld/reg/Hanmeimei-Lilei查看结果(会发现找不到对应的action返回404):

这里写图片描述

4、数据绑定

首先看一下都有哪些绑定数据的注解:

1.@RequestParam,绑定单个请求数据,可以是URL中的数据,表单提交的数据或上传的文件;

2.@PathVariable,绑定URL模板变量值;

3.@CookieValue,绑定Cookie数据;

4.@RequestHeader,绑定请求头数据;

5.@ModelAttribute,绑定数据到Model;

6.@SessionAttributes,绑定数据到Session;

7.@RequestBody,用来处理Content-Type不是application/x-www-form-urlencoded编码的内容,例如application/json, application/xml等;

8.@RequestPart,绑定“multipart/data”数据,并可以根据数据类型进项对象转换;

4.1、@RequestParam

为了验证文件绑定我们需要先做以下工作:

1.把commons-fileupload-1.3.1.jar和commons-io-2.2.jar两个jar包添加到我们项目。这里写图片描述

2.配置我们项目中的spring-servlet.xml文件使之支持文件上传,内容如下:

<!-- 支持上传文件 -->    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">        <!-- 设置上传文件的最大尺寸为1MB -->        <property name="maxUploadSize">            <value>1048576</value>        </property>      <property name="defaultEncoding">           <value>UTF-8</value>       </property>  </bean> 

其中maxUploadSize用于限制上传文件的最大大小,也可以不做设置,这样就代表上传文件的大小木有限制。defaultEncoding用于设置上传文件的编码格式,用于解决上传的文件中文名乱码问题。

下面就看具体如何使用:

添加一个DataBindController,里面有2个paramBind的action分别对应get和post请求:

package com.somnus.web.controller;  import javax.servlet.http.HttpServletRequest;  import org.springframework.stereotype.Controller;  import org.springframework.web.bind.ServletRequestUtils;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RequestMethod;  import org.springframework.web.bind.annotation.RequestParam;  import org.springframework.web.multipart.MultipartFile;  import org.springframework.web.multipart.MultipartHttpServletRequest;  import org.springframework.web.servlet.ModelAndView;  @Controller  @RequestMapping(value = "/databind")  public class DataBindController {      @RequestMapping(value="/parambind", method = {RequestMethod.GET})      public ModelAndView paramBind(){          ModelAndView modelAndView = new ModelAndView();            modelAndView.setViewName("parambind");            return modelAndView;      }      @RequestMapping(value="/parambind", method = {RequestMethod.POST})      public ModelAndView paramBind(HttpServletRequest request, @RequestParam("urlParam") String urlParam, @RequestParam("formParam") String formParam, @RequestParam("formFile") MultipartFile formFile){          //如果不用注解自动绑定,我们还可以像下面一样手动获取数据          String urlParam1 = ServletRequestUtils.getStringParameter(request, "urlParam", null);          String formParam1 = ServletRequestUtils.getStringParameter(request, "formParam", null);          MultipartFile formFile1 = ((MultipartHttpServletRequest) request).getFile("formFile");           ModelAndView modelAndView = new ModelAndView();            modelAndView.addObject("urlParam", urlParam);            modelAndView.addObject("formParam", formParam);            modelAndView.addObject("formFileName", formFile.getOriginalFilename());            modelAndView.addObject("urlParam1", urlParam1);            modelAndView.addObject("formParam1", formParam1);            modelAndView.addObject("formFileName1", formFile1.getOriginalFilename());            modelAndView.setViewName("parambindresult");            return modelAndView;      }  }  

在views文件夹中添加parambind.jsp和parambindresult.jsp两个视图,内容分别如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!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>      <form action="parambind?urlParam=AAA" method="post" enctype="multipart/form-data">           <input type="text" name="formParam" /><br/>           <input type="file" name="formFile" /><br/>          <input type="submit" value="Submit" />      </form>    </body>  </html>  
<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!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>      自动绑定数据:<br/><br/>      ${urlParam}<br/>      ${formParam}<br/>      ${formFileName}<br/><br/><br/><br/>      手动获取数据:<br/><br/>      ${urlParam1}<br/>      ${formParam1}<br/>      ${formFileName1}<br/>  </body>  </html>

运行项目,输入内容,选择上传文件:

这里写图片描述

提交查看结果:

这里写图片描述

可以看到绑定的数据已经获取到了。

上面我们演示了如何把数据绑定到单个变量,但在实际应用中我们通常需要获取的是model对象,别担心,我们不需要把数据绑定到一个个变量然后在对model赋值,只需要把model加入相应的action参数(这里不需要指定绑定数据的注解)SpringMVC会自动进行数据转换并绑定到model对象上,一切就是这么简单。测试如下:

添加一个Account类作为测试的model:

package com.somnus.web.model;  public class AccountModel {      private String username;      private String password;      public void setUsername(String username){          this.username=username;      }      public void setPassword(String password){          this.password=password;      }      public String getUsername(){          return this.username;      }      public String getPassword(){          return this.password;      }  }  

在DataBindController里面添加2个modelAutoBind的action分别对应get和post请求:

@RequestMapping(value="/modelautobind", method = {RequestMethod.GET})  public String modelAutoBind(HttpServletRequest request, Model model){      model.addAttribute("accountmodel", new AccountModel());      return "modelautobind";  }  @RequestMapping(value="/modelautobind", method = {RequestMethod.POST})  public String modelAutoBind(HttpServletRequest request, Model model, AccountModel accountModel){      model.addAttribute("accountmodel", accountModel);      return "modelautobindresult";  }  

在views文件夹中添加modelautobind.jsp和modelautobindresult.jsp 2个视图用于提交数据和展示提交的数据:

modelautobind.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>  <html>  <head>  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  <title>Insert title here</title>  </head>  <body>      <form:form modelAttribute="accountmodel" method="post">               用户名:<form:input path="username"/><br/>          密 码:<form:password path="password"/><br/>          <input type="submit" value="Submit" />      </form:form>    </body>  </html>  

modelautobindresult.jsp :

<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!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>      用户名:${accountmodel.username}<br/>      密 码:${accountmodel.password}  </body>  </html> 

运行测试:

这里写图片描述

用户名 输入caocao 密码 输入123456,提交:

这里写图片描述

可以看到结果显示正确,说明自动绑定成功。

1.关于@RequestParam的参数,这是一个@RequestParam的完整写法

@RequestParam(value=”username”, required=true, defaultValue=”AAA”)

value表示要绑定请求中参数的名字;

required表示请求中是否必须有这个参数,默认为true这是如果请求中没有要绑定的参数则返回404;

defaultValue表示如果请求中指定的参数值为空时的默认值;

要绑定的参数如果是值类型必须要有值否则抛异常,如果是引用类型则默认为null(Boolean除外,默认为false);

2.在刚才添加的2个action中可以看到返回类型和以前的不一样了由ModelAndView变成了String,这是由于Spring MVC 提供Model、ModelMap、Map让我们可以直接添加渲染视图需要的模型数据,在返回时直接指定对应视图名称就可以了。同时Map是继承于ModelMap的,而Model和ModelMap是继承于ExtendedModelMap的。

4.2、@PathVariable

用来绑定URL模板变量值

4.3、@CookieValue

在DataBindController添加cookiebind action,代码如下:

//@CookieValue Test  @RequestMapping(value="/cookiebind", method = {RequestMethod.GET})  public String cookieBind(HttpServletRequest request, Model model, @CookieValue(value="JSESSIONID", defaultValue="") String jsessionId){      model.addAttribute("jsessionId", jsessionId);      return "cookiebindresult";  }  

在views文件夹中添加一个cookiebindresult.jsp视图,代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!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>      ${jsessionId}  </body>  </html> 

运行测试:
这里写图片描述

可以看到已经获取到了sessionId。

注:@CookieValue 与@RequestParam 一样也有3个参数,其含义与的@RequestParam 参数含义相同。

4.4、@RequestHeader

用来绑定请求头中的数据,我们用@RequestHeader获取User-Agent 来做演示:

在DataBindController添加requestheaderbind action,代码如下:

@RequestMapping(value="/requestheaderbind", method = {RequestMethod.GET})  public String requestHeaderBind(HttpServletRequest request, Model model, @RequestHeader(value="User-Agent", defaultValue="") String userAgent){      model.addAttribute("userAgent", userAgent);      return "requestheaderbindresult";  }  

在views文件夹中添加一个requestheaderbindresult.jsp视图,代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!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>      ${userAgent}  </body>  </html> 

运行测试:

这里写图片描述

可以看到已经获取到了User-Agent 。

注:@RequestHeader 与@RequestParam 一样也有3个参数,其含义与的@RequestParam 参数含义相同。

4.5、@ModelAttribute

绑定数据到模型中。modelAutoBind action中我们将表单提交的数据添加到Model中的代码如下:

@RequestMapping(value="/modelautobind", method = {RequestMethod.POST})  public String modelAutoBind(HttpServletRequest request, Model model, AccountModel accountModel){      model.addAttribute("accountmodel", accountModel);      return "modelautobindresult";  }  

而借助于@ModelAttribute 我们可以更简单的讲数据添加到Model中,把上面的代码修改为:

@RequestMapping(value="/modelautobind", method = {RequestMethod.POST})  public String modelAutoBind(HttpServletRequest request, @ModelAttribute("accountmodel") AccountModel accountModel){      return "modelautobindresult";  }  

运行测试如下:

这里写图片描述

可以看到依然成功的绑定了提交的数据。

4.6、@SessionAttributes

Model中的数据作用域是Request级别的,也就是说在一个Request请求中是获取不到其它Request请求的Model的数据的。但我们可以用@SessionAttributes 把数据存储到session中,来保持多次请求间数据,这样就可以来实现比如分步骤提交表单等需求。下面我们来看如何分2步把数据绑定到AccountModel中:

在DataBindController上添加:

@SessionAttributes(value = "sessionaccountmodel") 

在DataBindController添加usernamebind和passwordbind action,代码如下:

@RequestMapping(value="/usernamebind", method = {RequestMethod.GET})  public String userNameBind( Model model, AccountModel accountModel){      model.addAttribute("sessionaccountmodel", new AccountModel());      return "usernamebind";  }  @RequestMapping(value="/usernamebind", method = {RequestMethod.POST})  public String userNameBindPost( @ModelAttribute("sessionaccountmodel") AccountModel accountModel){      //重定向到密码绑定测试      return "redirect:passwordbind";  }  @RequestMapping(value="/passwordbind", method = {RequestMethod.GET})  public String passwordBind(@ModelAttribute("sessionaccountmodel") AccountModel accountModel){      return "passwordbind";  }  @RequestMapping(value="/passwordbind", method = {RequestMethod.POST})  public String passwordBindPost(@ModelAttribute("sessionaccountmodel") AccountModel accountModel, SessionStatus status){      //销毁@SessionAttributes存储的对象      status.setComplete();      //显示绑定结果      return "sessionmodelbindresult";  }  

由于我们在controller上指定了@SessionAttributes,所以在@ModelAttribute(“xxx”)注解的参数会直接在@SessionAttributes中查找名为”xxx”的对象,如果没有找到则调用@ModelAttribute(“xxx”)注解的方法返回对象并存入@SessionAttributes(如果没有找到且没有@ModelAttribute(“xxx”)注解的方法就会抛出HttpSessionRequiredException)。当执行到最后一步就可以调用SessionStatus .setComplete()方法把@SessionAttributes中保存对象销毁了(不会清除HttpSession中的数据)。

在views文件夹中添加usernamebind.jsp、passwordbind.jsp和sessionmodelbindresult.jsp视图内容分别如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>  <html>  <head>  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  <title>Insert title here</title>  </head>  <body>      <form:form modelAttribute="sessionaccountmodel" method="post">               用户名:<form:input path="username"/><br/>          <input type="submit" value="Submit" />      </form:form>    </body>  </html> 
<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>  <html>  <head>  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  <title>Insert title here</title>  </head>  <body>      <form:form modelAttribute="sessionaccountmodel" method="post">               密 码:<form:password path="password"/><br/>          <input type="submit" value="Submit" />      </form:form>    </body>  </html> 
<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!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>      用户名:${sessionaccountmodel.username}<br/>      密 码:${sessionaccountmodel.password}  </body>  </html> 

运行测试:

这里写图片描述

这里写图片描述

这里写图片描述

可以看到我们已经成功的分2步把数据绑定到AccountModel中了。

注:

@SessionAttributes有value和types两个参数其中value指明要对象的名称,types指定要绑定对象的类型,
如@SessionAttributes(value= “sessionaccountmodel”, types=AccountModel.class)两者是and关系,需要同时满足。也可以同时指定多个value和types
如:@SessionAttributes(value = {“aa”, “aa”} , types={XXX.class, YYY.class}) 。

4.7、@RequestBody

调用合适的MessageConvert来把非application/x-www-form-urlencoded请求中的内容转换为指定的对象它通常与@ResponseBody合用,@ResponseBody与.@RequestBody刚好相反,他把指定的对象转换为合适的内容(请求头为Accept:application/json 则返回json数据)并返回。这里我们用一个ajax请求做演示:
由于Spring默认解析json用的是Jackson,所以我们这里要把三个包添加到我们项目。
这里写图片描述

修改Account让其继承Serializable接口,并添加一个空的构造函数(为了Jackson做转换)。

在DataBindController添加requestBodyBindaction,代码如下:

@RequestMapping(value="/requestbodybind", method = {RequestMethod.GET})  public String requestBodyBind(Model model){      model.addAttribute("accountmodel", new AccountModel());      return "requestbodybind";  }  @RequestMapping(value="/requestbodybind", method = {RequestMethod.POST})  public @ResponseBody AccountModel requestBodyBind(@RequestBody AccountModel accountModel){      return accountModel;  }  

在views文件夹中添加requestbodybind.jsp视图内容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>  <%  String path = request.getContextPath();  String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  %>  <html>  <head>  <script src="<%=basePath%>js/jquery-2.1.0.min.js"></script>  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  <title>Insert title here</title>  </head>  <body>      <form:form modelAttribute="accountmodel" method="post">               用户名:<form:input path="username"/><br/>          密 码:<form:password path="password"/><br/>          <input type="button" id="submit" value="Submit" />      </form:form>       <script type="text/javascript">          $(function() {               $("#submit").click(function() {                     var postdata = '{"username":"' + $('#username').val() + '","password":"' + $('#password').val() + '"}';                     $.ajax({                        type : 'POST',                        contentType : 'application/json',                        url : '<%=basePath%>/databind/requestbodybind',                          processData : false,                        dataType : 'json',                        data : postdata,                        success : function(data) {                            alert('username : '+data.username+'\npassword : '+data.password);                        },                        error : function() {                            alert('error...');                        }                    });               });          });      </script>   </body>  </html>

运行测试:

结果正确,证明转换成功。

4.8、@RequestPart

绑定“multipart/form-data“类型数据,支持javax.servlet.http.Part文件上传,并可可以进行类型转换,详见官方文档:
http://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/htmlsingle/#new-in-3.1-mvc-requestpart

5、数据验证

前面中我们展示了如何绑定数据,绑定完数据之后如何确保我们得到的数据的正确性?
这里我们采用Hibernate-validator来进行验证,Hibernate-validator实现了JSR-303验证框架支持注解风格的验证。

这里写图片描述

修改之前项目中的spring-mvc.xml文件,如下:

<mvc:annotation-driven validator="validator" conversion-service="conversion-service" />  <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">      <property name="providerClass"  value="org.hibernate.validator.HibernateValidator"/>      <!--不设置则默认为classpath下的 ValidationMessages.properties -->      <property name="validationMessageSource" ref="validatemessageSource"/>  </bean>  <bean id="conversion-service" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />  <bean id="validatemessageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">        <property name="basename" value="classpath:validatemessages"/>        <property name="fileEncodings" value="utf-8"/>        <property name="cacheSeconds" value="120"/>    </bean> 

其中这里写图片描述中的classpath:validatemessages为注解验证消息所在的文件,需要我们在resources文件夹下添加。

这里写图片描述

name.not.empty=名称不能为空。age.not.inrange=年龄超出范围。email.not.correct=邮箱地址不正确。email.not.empty=电子邮件不能为空。

在com.somnus.web.controller包中添加一个ValidateController.java内容如下:

package com.somnus.web.controller;  import java.security.NoSuchAlgorithmException;  import javax.validation.Valid;  import org.springframework.stereotype.Controller;  import org.springframework.ui.Model;  import org.springframework.validation.BindingResult;  import org.springframework.web.bind.annotation.ModelAttribute;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RequestMethod;  import com.demo.web.models.ValidateModel;  @Controller  @RequestMapping(value = "/validate")  public class ValidateController {      @RequestMapping(value="/test", method = {RequestMethod.GET})      public String test(Model model){          if(!model.containsAttribute("contentModel")){              model.addAttribute("contentModel", new Validate());          }          return "validatetest";      }      @RequestMapping(value="/test", method = {RequestMethod.POST})      public String test(Model model, @Valid @ModelAttribute("contentModel") Validate validate, BindingResult result) throws NoSuchAlgorithmException{          //如果有验证错误 返回到form页面          if(result.hasErrors())              return test(model);          return "validatesuccess";           }  }  

其中@Valid @ModelAttribute(“contentModel”) ValidateModel validateModel的@Valid 意思是在把数据绑定到@ModelAttribute(“contentModel”) 后就进行验证。

在com.somnus.web.model包中添加一个Validate.java内容如下:

package com.somnus.web.model;  import org.hibernate.validator.constraints.Email;  import org.hibernate.validator.constraints.NotEmpty;  import org.hibernate.validator.constraints.Range;  public class Validate{      @NotEmpty(message="{name.not.empty}")      private String name;      @Range(min=0, max=150,message="{age.not.inrange}")      private String age;      @NotEmpty(message="{email.not.empty}")      @Email(message="{email.not.correct}")      private String email;      public void setName(String name){          this.name=name;      }      public void setAge(String age){          this.age=age;      }      public void setEmail(String email){          this.email=email;      }      public String getName(){          return this.name;      }      public String getAge(){          return this.age;      }      public String getEmail(){          return this.email;      }  }  

在views文件夹中添加validatetest.jsp和validatesuccess.jsp两个视图,内容分别如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>  <html>  <head>  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  <title>Insert title here</title>  </head>  <body>      <form:form modelAttribute="contentModel" method="post">               <form:errors path="*"></form:errors><br/><br/>          name:<form:input path="name" /><br/>          <form:errors path="name"></form:errors><br/>          age:<form:input path="age" /><br/>          <form:errors path="age"></form:errors><br/>          email:<form:input path="email" /><br/>          <form:errors path="email"></form:errors><br/>          <input type="submit" value="Submit" />      </form:form>    </body>  </html> 
<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!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>  </html> 
1 0
原创粉丝点击