SpringMVC_One

SpringMVC的优势 (面试)

清晰的角色划分:

  • 前端控制器(DispatcherServlet)
  • 请求到处理器映射器(HandlerMapping)
  • 处理器适配器(HandlerAdapter)
  • 视图解析器(ViewResolver)
  • 处理器或页面控制器(Controller)
  • 验证器( Validator)
  • 命令对象(Command 请求参数绑定到的对象就叫命令对象)
  • 表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)。

2、分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要。

3、由于命令对象就是一个POJO,无需继承框架特定API,可以使用命令对象直接作为业务对象。

4、和Spring 其他框架无缝集成,是其它Web框架所不具备的。

5、可适配,通过HandlerAdapter可以支持任意的类作为处理器。

6、可定制性,HandlerMapping、ViewResolver等能够非常简单的定制。

7、功能强大的数据验证、格式化、绑定机制。

8、利用Spring提供的Mock对象能够非常简单的进行Web层单元测试。

9、本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。

10、强大的JSP标签库,使JSP编写更容易。

………………还有比如RESTful风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配置支持等等


SpringMVC和Struts2的优略分析 (面试)

共同点:

  • 它们都是表现层框架,都是基于MVC模型编写的。
  • 它们的底层都离不开原始ServletAPI(HttpServletRequest、HttpServletResponse…)。
  • 它们处理请求的机制都是一个核心控制器。

区别:

  • Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
  • Spring MVC 是基于方法设计的,而Struts2是基于类,Struts2每次执行都会创建一个动作类。所以Spring MVC 会稍微比 Struts2 快些。
  • Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便 ,而struts2处理ajax的时候,需要导入一个struts2的插件包,并通过返回类型指定ajax的json数据。
  • (JSR303 是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面,就可以在需要校验的时候进行校验了。) (回去之后,有兴趣可以搜一下springMVC校验机制)
  • Struts2 的OGNL 表达式使页面的开发效率相比Spring MVC 更高些,但执行效率并没有比JSTL提升,尤其是struts2的表单标签,远没有html执行效率高。

SpringMVC的入门

导包配置xml:

    1. <!-- 版本锁定 -->
    1. <properties>
    1. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    1. <maven.compiler.source>1.8</maven.compiler.source>
    1. <maven.compiler.target>1.8</maven.compiler.target>
    1. <spring.version>5.0.2.RELEASE</spring.version>
    1. </properties>
    1. <dependencies>
    1. <dependency>
    1. <groupId>org.springframework</groupId>
    1. <artifactId>spring-context</artifactId>
    1. <version>${spring.version}</version>
    1. </dependency>
    1. <dependency>
    1. <groupId>org.springframework</groupId>
    1. <artifactId>spring-web</artifactId>
    1. <version>${spring.version}</version>
    1. </dependency>
    1. <dependency>
    1. <groupId>org.springframework</groupId>
    1. <artifactId>spring-webmvc</artifactId>
    1. <version>${spring.version}</version>
    1. </dependency>
    1. <dependency>
    1. <groupId>javax.servlet</groupId>
    1. <artifactId>servlet-api</artifactId>
    1. <version>2.5</version>
    1. <scope>provided</scope>
    1. </dependency>
    1. <dependency>
    1. <groupId>javax.servlet.jsp</groupId>
    1. <artifactId>jsp-api</artifactId>
    1. <version>2.0</version>
    1. <scope>provided</scope>
    1. </dependency>
    1. </dependencies>

配置web.xml 在web.xml配置文件中核心控制器DispatcherServlet

    1. <!-- SpringMVC的核心控制器 -->
    1. <servlet>
    1. <servlet-name>dispatcherServlet</servlet-name>
    1. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    1. <!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 -->
    1. <init-param>
    1. <param-name>contextConfigLocation</param-name>
    1. <param-value>classpath:springmvc.xml</param-value>
    1. </init-param>
    1. <!-- 配置servlet启动时加载对象 -->
    1. <load-on-startup></load-on-startup>
    1. </servlet>
    1. <servlet-mapping>
    1. <servlet-name>dispatcherServlet</servlet-name>
    1. <url-pattern>/</url-pattern>
    1. </servlet-mapping>

配置编写springmvc.xml的配置文件

在resources下创建springmvc.xml

    1. <?xml version="1.0" encoding="UTF-8"?>
    1. <beans xmlns="http://www.springframework.org/schema/beans"
    1. xmlns:mvc="http://www.springframework.org/schema/mvc"
    1. xmlns:context="http://www.springframework.org/schema/context"
    1. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    1. xsi:schemaLocation="
    1. http://www.springframework.org/schema/beans
    1. http://www.springframework.org/schema/beans/spring-beans.xsd
    1. http://www.springframework.org/schema/mvc
    1. http://www.springframework.org/schema/mvc/spring-mvc.xsd
    1. http://www.springframework.org/schema/context
    1. http://www.springframework.org/schema/context/spring-context.xsd">
    1. <!-- 1:配置spring创建容器时要扫描的包,可以使用@Controller注解 -->
    1. <context:component-scan base-package="com.it"></context:component-scan>
    1. <!-- 2:配置视图解析器 -->
    1. <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    1. <property name="prefix" value="/WEB-INF/pages/"></property>
    1. <property name="suffix" value=".jsp"></property>
    1. </bean>
    1. <!-- 3:配置spring开启注解mvc的支持,自动开启处理器映射器和处理器适配器 -->
    1. <mvc:annotation-driven></mvc:annotation-driven>
    1. </beans>

v创建index.jsp

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    1. <html>
    1. <head>
    1. <title>Title</title>
    1. </head>
    1. <body>
    1. <h3>入门案例</h3>
    1. <a href="hello">入门案例</a>
    1. </body>
    1. </html>

创建类HelloController.java

    1. /**
    1. * 控制器
    1. */
    1. @Controller
    1. public class HelloController {
    1. // 请求参数
    1. @RequestMapping(path = "/hello")
    1. public String sayHello(){
    1. System.out.println("Hello SpringMVC!!");
    1. return "success";// 响应结果
    1. }
    1. }

在WEB-INF下创建pages的文件夹,创建success.jsp

    1. <body>
    1. <h1>访问成功</h1>
    1. </body>

案例执行流程


请求参数的绑定

1.1.1 请求参数的绑定说明

(1)绑定机制

【1】表单提交的数据都是k=v格式的 username=haha&password=123

【2】SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的

【3】要求:提交表单的name和参数的名称是相同的

(2)支持的数据类型

【1】基本数据类型和字符串类型

【2】实体类型(JavaBean)

【3】集合数据类型(List、map集合等)

基本数据类型和字符串类型

(1)提交表单的name和参数的名称是相同的

(2)区分大小写

创建param.jsp

    1. <body>
    1. <h3>传递参数</h3>
    1. <%--↓提交数据--%>
    1. <a href="param/testParam?username=张三&age=18">入门案例</a>
    1. </body>

创建ParamController.java

    1. @Controller
    1. @RequestMapping(path = "/param")
    1. public class ParamController {
    1. // 请求参数
    1. @RequestMapping(path = "/testParam")
    1. // 接收数据
    1. public String testParam(String username,Integer age){
    1. System.out.println("params测试:username:"+username+" age:"+age);
    1. return "success";// 响应结果
    1. }
    1. }

实体类型(JavaBean)

(1)提交表单的name和JavaBean中的属性名称需要一致

(2)如果一个JavaBean类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性 例如:address.name

创建类User.java

    1. public class User {
    1. private String username;
    1. private Integer age;
    1. }

在Controller中定义

    1. @RequestMapping(value = "/testParam")
    1. public String testParam(User user){
    1. System.out.println("欢迎执行ParamController中的testParam方法!user:"+user);
    1. return "success";// 执行视图解析器 /WEB-INF/page/success.jsp
    1. }

创建Account.java

    1. public class Account {
    1. private String name;
    1. private String password;
    1. private Double money;
    1. private User user;
    1. }

param.jsp

    1. <form action="param/saveAccount" method="post">
    1. 账号:<input type="text" name="name"/><br>
    1. 密码:<input type="text" name="password"/><br>
    1. 金额:<input type="text" name="money"/><br>
    1. 用户姓名:<input type="text" name="user.username"/><br>
    1. 用户年龄:<input type="text" name="user.age"/><br>
    1. <input type="submit" value="提交"/>
    1. </form>

ParamController.java

    1. @RequestMapping(path = "/saveAccount")
    1. public String testParam(Account account){
    1. System.out.println(account);
    1. return "success";// 响应结果
    1. }

请求参数中文乱码的解决

在web.xml中配置Spring提供的过滤器类

    1. <!-- 配置过滤器,解决中文乱码的问题 -->
    1. <filter>
    1. <filter-name>characterEncodingFilter</filter-name>
    1. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    1. <!-- 指定字符集 -->
    1. <init-param>
    1. <param-name>encoding</param-name>
    1. <param-value>UTF-8</param-value>
    1. </init-param>
    1. </filter>
    1. <filter-mapping>
    1. <filter-name>characterEncodingFilter</filter-name>
    1. <url-pattern>/*</url-pattern>
    1. </filter-mapping>

给集合属性数据封装(了解)

(1)JSP页面编写方式:list[0].属性

(2)JSP页面编写方式:map[‘one’].属性

param.jsp

    1. <form action="param/saveAccount" method="post">
    1. 账号:<input type="text" name="name"/><br>
    1. 密码:<input type="text" name="password"/><br>
    1. 金额:<input type="text" name="money"/><br>
    1. 用户姓名:<input type="text" name="user.username"/><br>
    1. 用户年龄:<input type="text" name="user.age"/><br>
    1. 用户姓名(list):<input type="text" name="list[0].username"/><br>
    1. 用户年龄(list):<input type="text" name="list[0].age"/><br>
    1. 用户姓名(list):<input type="text" name="list[1].username"/><br>
    1. 用户年龄(list):<input type="text" name="list[1].age"/><br>
    1. 用户姓名(map):<input type="text" name="map['one'].username"/><br>
    1. 用户年龄(map):<input type="text" name="map['one'].age"/><br>
    1. 用户姓名(map):<input type="text" name="map['two'].username"/><br>
    1. 用户年龄(map):<input type="text" name="map['two'].age"/><br>
    1. <input type="submit" value="提交"/>
    1. </form>

在Account.java中添加:

    1. private List<User> list;
    1. private Map<String,User> map;

自定义类型转换器(了解)

(1)表单提交的任何数据类型全部都是字符串类型,但是后台定义Integer类型,数据也可以封装上,说明SpringMVC框架内部会默认进行数据类型转换。

(2)如果想自定义数据类型转换,可以实现Converter的接口

在User.java中添加:

    1. public class User {
    1. private String username;
    1. private Integer age;
    1. private Date birthday;
    1. }

param.jsp

    1. <form action="param/saveUser" method="post">
    1. 姓名:<input type="text" name="username"/><br>
    1. 年龄:<input type="text" name="age"/><br>
    1. 生日:<input type="text" name="birthday"/><br>
    1. <input type="submit" value="提交"/>
    1. </form>

ParamController.java

    1. @RequestMapping(path = "/saveUser")
    1. public String saveUser(User user){
    1. System.out.println(user);
    1. return "success";// 响应结果
    1. }

自定义类型转换器

    1. package com.it.utils;
    1. import org.springframework.core.convert.converter.Converter;
    1. import java.text.DateFormat;
    1. import java.text.SimpleDateFormat;
    1. import java.util.Date;
    1. /**
    1. * 把字符串转换成日期的转换器
    1. */
    1. public class StringToDateConverter implements Converter<String, Date> {
    1. /**
    1. * 进行类型转换的方法
    1. */
    1. public Date convert(String source) {
    1. // 判断
    1. if(source == null) {
    1. throw new RuntimeException("参数不能为空");
    1. }
    1. try {
    1. DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    1. // 解析字符串
    1. Date date = df.parse(source);
    1. return date;
    1. } catch (Exception e) {
    1. throw new RuntimeException("类型转换错误");
    1. }
    1. }
    1. }

【2】注册自定义类型转换器,在springmvc.xml配置文件中编写配置

    1. <!-- 注册自定义类型转换器 -->
    1. <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    1. <property name="converters">
    1. <set>
    1. <bean class="com.it.utils.StringToDateConverter"></bean>
    1. </set>
    1. </property>
    1. </bean>
    1. <!-- 配置spring开启注解mvc的支持 -->
    1. <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

常用注解

@RequestParam注解

作用:

把请求中指定名称的参数给控制器中的形参赋值。

属性:

value:请求参数中的名称。

required:请求参数中是否必须提供此参数。默认值:true。表示必须提供,如果不提供将报错。

defaultValue:表示默认值,如果不传递值


创建anno.jsp

    1. <body>
    1. <h3>RequestParam入门案例</h3>
    1. <a href="anno/testRequestParam?name=哈哈&age=22">RequestParam</a>
    1. </body>

创建AnnoController.java

    1. @Controller
    1. @RequestMapping(path = "/anno")
    1. public class AnnoController {
    1. // 请求参数
    1. @RequestMapping(path = "/testRequestParam")
    1. public String testRequestParam(@RequestParam(value = "name") String username,
    1. @RequestParam(value="age",required = true)Integer age){
    1. System.out.println("Hello SpringMVC!!,测试@RequestParam");
    1. System.out.println(username);
    1. System.out.println(age);
    1. return "success";// 响应结果
    1. }
    1. }

@RequestBody注解

作用:

1:@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的)

2:用于获取请求体内容。直接使用得到是key=value&key=value…结构的数据。 get请求方式不适用。

属性:

required:是否必须有请求体。默认值是:true。

当取值为true时,get请求方式会报错。

如果取值为false,get请求得到是null。

    1. <h3>@RequestBody</h3>
    1. post请求jsp代码: <br>
    1. <!-- request body注解 -->
    1. <form action="anno/testRequestBody" method="post">
    1. 用户名称:<input type="text" name="username" ><br/>
    1. 用户密码:<input type="password" name="password" ><br/>
    1. 用户年龄:<input type="text" name="age" ><br/>
    1. <input type="submit" value="保存">
    1. </form>
    1. get请求jsp代码: <br>
    1. <a href="anno/testRequestBody?body=test">requestBody注解get请求</a>
    1. // 请求参数
    1. @RequestMapping(path = "/testRequestBody")
    1. public String testRequestBody(@RequestBody(required = false) String body){
    1. System.out.println("Hello SpringMVC!!,测试@RequestParam");
    1. System.out.println(body);
    1. return "success";// 响应结果
    1. }

@PathVariable注解

作用: 
用于绑定url中的占位符。例如:请求url中 /delete/{id}/{name},这个{id},{name}就是url占位符。

url支持占位符是spring3.0之后加入的。是springmvc支持restful风格URL的一个重要标志。

属性:

value:用于指定url中占位符名称。

required:是否必须提供占位符。

    1. <h3>@PathVariable注解</h3>
    1. <!-- PathVariable注解 -->
    1. <a href="anno/testPathVariable/100">pathVariable注解</a>
    1. // 请求参数
    1. @RequestMapping(path = "/testPathVariable/{uid}")
    1. public String testPathVariable(@PathVariable(value = "uid") Integer id){
    1. System.out.println("Hello SpringMVC!!,测试@PathVariable");
    1. System.out.println(id);
    1. return "success";// 响应结果
    1. }

REST风格URL

什么是rest

REST(英文:Representational State Transfer,简称REST,说的意思是:表现层状态转变,或者叫做 “表述性状态转移”)描述了一个架构样式的网络系统,比如 web 应用程序。它首次出现在 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一。在目前主流的三种Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及XML-RPC更加简单明了,无论是对URL的处理还是对Payload的编码,REST都倾向于用更加简单轻量的方法设计和实现。值得注意的是REST并没有一个明确的标准,而更像是一种设计的风格。

它本身并没有什么实用性,其核心价值在于如何设计出符合REST风格的网络接口。

restful的优点

它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。

restful的特性:

资源(Resources):网络上的一个实体,或者说是网络上的一个具体信息。

它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。要获取这个资源,访问它的URI就可以,因此 URI 即为每一个资源的独一无二的识别符。

表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层 (Representation)。

比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。

状态转化(State Transfer):每发出一个请求,就代表了客户端和服务器的一次交互过程。

HTTP协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是 “表现层状态转化”。具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。

传统的实例:唯一的URL地址(统一资源定位符),找到对应的资源


基于HiddentHttpMethodFilter的示例

作用:

由于浏览器 form 表单只支持 GET 与 POST 请求,而DELETE、PUT 等 method 并不支持,Spring3.0 添加了一个过滤器,可以将浏览器请求改为指定的请求方式,发送给我们的控制器方法,使得支持 GET、POST、PUT 与DELETE 请求。

在web.xml中配置该过滤器。

    1. <filter>
    1. <filter-name>hiddenHttpMethodFilter</filter-name>
    1. <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    1. </filter>
    1. <filter-mapping>
    1. <filter-name>hiddenHttpMethodFilter</filter-name>
    1. <url-pattern>/*</url-pattern>
    1. </filter-mapping>

第二步:请求方式必须使用post请求。

第三步:按照要求提供_method请求参数,该参数的取值就是我们需要的请求方式。

anno.jsp

    1. resfful风格:jsp中示例代码:
    1. <!-- 保存 -->
    1. <form action="anno/testPathVariable" method="post">
    1. 用户名称:<input type="text" name="username"><br/>
    1. <!-- <input type="hidden" name="_method" value="POST"> -->
    1. <input type="submit" value="保存"></form>
    1. <hr/>
    1. <!-- 更新 -->
    1. <form action="anno/testPathVariable" method="post">
    1. 用户名称:<input type="text" name="username"><br/>
    1. <input type="hidden" name="_method" value="PUT">
    1. <input type="submit" value="更新">
    1. </form>
    1. <hr/>
    1. <!-- 删除 -->
    1. <form action="anno/testPathVariable/1" method="post">
    1. <input type="hidden" name="_method" value="DELETE">
    1. <input type="submit" value="删除">
    1. </form>
    1. <hr/>
    1. <!-- 查询一个 -->
    1. <form action="anno/testPathVariable/1" method="post">
    1. <input type="hidden" name="_method" value="GET">
    1. <input type="submit" value="查询">
    1. </form>
    1. <hr/>
    1. // 请求参数
    1. @RequestMapping(path = "/testPathVariable",method = RequestMethod.POST)
    1. public String save(User user){
    1. System.out.println("Hello SpringMVC!!,测试@PathVariable,新增-请求方式Post");
    1. System.out.println(user);
    1. return "success";// 响应结果
    1. }
    1. // 请求参数
    1. @RequestMapping(path = "/testPathVariable",method = RequestMethod.PUT)
    1. public String update(User user){
    1. System.out.println("Hello SpringMVC!!,测试@PathVariable,更新-请求方式Put");
    1. System.out.println(user);
    1. return "success";// 响应结果
    1. }
    1. // 请求参数
    1. @RequestMapping(path = "/testPathVariable/{uid}",method = RequestMethod.DELETE)
    1. public String delete(@PathVariable(value = "uid") Integer id){
    1. System.out.println("Hello SpringMVC!!,测试@PathVariable,删除-请求方式Delete");
    1. System.out.println(id);
    1. return "success";// 响应结果
    1. }
    1. // 请求参数
    1. @RequestMapping(path = "/testPathVariable/{uid}",method = RequestMethod.GET)
    1. public String findById(@PathVariable(value = "uid") Integer id){
    1. System.out.println("Hello SpringMVC!!,测试@PathVariable,查询一个-请求方式Get");
    1. System.out.println(id);
    1. return "success";// 响应结果
    1. }

但是我们可以在控制台看到结果,说明执行了对应的方法,但是在响应到Jsp页面的时候,Jsp页面不支持PUT和DELETE请求的响应,所以抛出异常,我们可以使用@ResponseBody(后面讲)表示不再响应页面,即视图解析器将失效,以文本的形式返回,用在ajax的应用场景(返回文本或者json)

    1. // 修改是PUT协议
    1. @RequestMapping(value = "/testPathVariable",method = RequestMethod.PUT)
    1. public @ResponseBody String update(User user){
    1. System.out.println("put请求,修改");
    1. System.out.println(user);
    1. return "success";
    1. }
    1. // 删除是DELETE协议
    1. @RequestMapping(value = "/testPathVariable/{id}",method = RequestMethod.DELETE)
    1. public @ResponseBody String delete(@PathVariable(name = "id") Integer id,User user){
    1. System.out.println("delete请求,删除");
    1. System.out.println(id);
    1. System.out.println(user);
    1. return "success";
    1. }

@RequestHeader注解

作用:

用于获取请求消息头。

属性:

value:提供消息头名称

required:是否必须有此消息头

注:

在实际开发中一般不怎么用。

    1. <h3>测试@RequestHeader注解</h3>
    1. <!-- RequestHeader注解 -->
    1. <a href="anno/testRequestHeader">获取请求消息头</a>
    1. // 请求参数
    1. @RequestMapping(path = "/testRequestHeader")
    1. public String testRequestHeader(@RequestHeader(value="accept")String requestHeader){
    1. System.out.println("Hello SpringMVC!!,测试@RequestHeader");
    1. System.out.println(requestHeader);
    1. return "success";// 响应结果
    1. }

@CookieValue注解

作用:

用于把指定cookie名称的值传入控制器方法参数。

属性:

value:指定cookie的名称。

required:是否必须有此cookie。

    1. <h3>测试@CookieValue注解</h3>
    1. <!-- CookieValue注解 -->
    1. <a href="anno/testCookieValue">CookieValue注解</a>
    1. @RequestMapping(path = "/testCookieValue")
    1. public String testCookieValue(@CookieValue(value = "JSESSIONID")String cookieValue){
    1. System.out.println("Hello SpringMVC!!,测试@CookieValue");
    1. System.out.println(cookieValue);
    1. return "success";// 响应结果
    1. }

@ModelAttribute注解

作用:

该注解是SpringMVC4.3版本以后新加入的。它可以用于修饰方法和参数。

出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。

出现在参数上,获取指定的数据给参数赋值。

属性:

value:用于获取数据的key。key可以是POJO的属性名称,也可以是map结构的key。

应用场景:

当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。

例如:

我们在编辑一个用户时,用户有一个创建信息字段,该字段的值是不允许被修改的。在提交表单数据是肯定没有此字段的内容,一旦更新会把该字段内容置为null,此时就可以使用此注解解决问题。


基于POJO属性的基本使用

anno.jsp

    1. <h3>测试@ModelAttribute注解</h3>
    1. 需求: 修改用户信息,要求用户的日期不能修改 jsp的代码:
    1. <!-- 修改用户信息 -->
    1. <form action="anno/testModelAttribute" method="post">
    1. 用户名称:<input type="text" name="username" ><br/>
    1. 用户年龄:<input type="text" name="age" ><br/>
    1. <input type="submit" value="保存">
    1. </form>

AnnoController.java

    1. // ModelAttribute的用法
    1. @ModelAttribute // 在执行的方法之前运行
    1. public void showModel(User user) {
    1. System.out.println("执行了showModel方法"+user);
    1. user.setBirthday(new Date());
    1. }
    1. /** * 模拟修改用户方法 * @param user * @return */
    1. @RequestMapping("/testModelAttribute")
    1. public String testModelAttribute(User user) {
    1. System.out.println("控制器中处理请求的方法:修改用户:"+user);
    1. return "success";
    1. }

基于Map的应用场景一:ModelAttribute修饰方法带返回值

    1. <h3>测试@ModelAttribute注解</h3>
    1. 需求: 修改用户信息,要求用户的日期不能修改 jsp的代码:
    1. <!-- 修改用户信息 -->
    1. <form action="anno/testModelAttribute" method="post">
    1. 用户名称:<input type="text" name="username" ><br/>
    1. 用户年龄:<input type="text" name="age" ><br/>
    1. <input type="submit" value="保存">
    1. </form>

AnnoController.java

    1. @ModelAttribute // 在执行的方法之前运行
    1. public User showModel(String username) {
    1. //模拟去数据库查询
    1. User user = findUserByName(username);
    1. System.out.println("执行了showModel方法"+user);
    1. return user;
    1. }
    1. /** * 模拟修改用户方法 * @param user * @return */
    1. @RequestMapping("/testModelAttribute")
    1. public String testModelAttribute(User user) {
    1. System.out.println("控制器中处理请求的方法:修改用户:"+user);
    1. return "success";
    1. }
    1. /** * 模拟去数据库查询 * @param username * @return User*/
    1. private User findUserByName(String username) {
    1. User user = new User();
    1. user.setUsername(username);
    1. user.setAge();
    1. user.setBirthday(new Date());
    1. return user;
    1. }

基于Map的应用场景二:ModelAttribute修饰方法不带返回值

    1. @ModelAttribute // 在执行的方法之前运行
    1. public void showModel(String username, Map<String,User> maps) {
    1. //模拟去数据库查询
    1. User user = findUserByName(username);
    1. maps.put("abc",user);
    1. System.out.println("执行了showModel方法"+user);
    1. }
    1. /** * 模拟修改用户方法 * @param user */
    1. @RequestMapping("/testModelAttribute")
    1. public String testModelAttribute(@ModelAttribute(value = "abc") User user) {
    1. System.out.println("控制器中处理请求的方法:修改用户:"+user);
    1. return "success";
    1. }
    1. /** * 模拟去数据库查询 * @param username * @return User*/
    1. private User findUserByName(String username) {
    1. User user = new User();
    1. user.setUsername(username);
    1. user.setAge();
    1. user.setBirthday(new Date());
    1. return user;
    1. }

@SessionAttributes注解

    1. 作用:
    1. 用于多次执行控制器方法间的参数共享。 放置到类的上面。
    1. 属性:
    1. value:用于指定存入的属性名称
    1. type:用于指定存入的数据类型。
    1. 相当于将数据存放到Session中。

最好:

    1. <h3>测试@SessionAttributes注解</h3>
    1. <!-- SessionAttribute注解的使用 -->
    1. <a href="anno/sessionAttributePut">存入SessionAttribute</a> <hr/>
    1. <a href="anno/sessionAttributeGet">取出SessionAttribute</a> <hr/>
    1. <a href="anno/sessionAttributeClean">清除SessionAttribute</a>

AnnoController.java

    1. @Controller
    1. @RequestMapping(path = "/anno")
    1. @SessionAttributes(value ={"username","password"},types={Integer.class})
    1. public class AnnoController {
    1. /**
    1. * * 把数据存入SessionAttribute
    1. * * @param model
    1. * * @return
    1. * * Model是spring提供的一个接口,该接口有一个实现类ExtendedModelMap *
    1. * 该类继承了ModelMap,而ModelMap就是LinkedHashMap子类 */
    1. @RequestMapping("/sessionAttributePut")
    1. public String testPut(Model model){
    1. System.out.println("把数据存入SessionAttribute");
    1. model.addAttribute("username", "泰斯特");
    1. model.addAttribute("password","123456");
    1. model.addAttribute("age", );
    1. //跳转之前将数据保存到username、password和age中,因为注解@SessionAttribute中有这几个参数
    1. return "success";
    1. }
    1. /**
    1. * * 获取SessionAttribute
    1. */
    1. @RequestMapping("/sessionAttributeGet")
    1. public String testGet(ModelMap model){
    1. System.out.println("获取SessionAttribute");
    1. System.out.println(model.get("username")+";"+model.get("password")+";"+model.get("age"));
    1. return "success";
    1. }
    1. /**
    1. * * 清空SessionAttribute
    1. */
    1. @RequestMapping("/sessionAttributeClean")
    1. public String complete(SessionStatus sessionStatus){
    1. System.out.println("清空SessionAttribute");
    1. sessionStatus.setComplete();
    1. return "success";
    1. }
    1. }

SpringMVC_One的更多相关文章

  1. 初识Spring MVC

    1.什么是Spring MVC? Spring MVC属于SpringFrameWork的后续产品,它提供了构建 Web 应用程序的全功能 MVC 模块,与Struts2一样是一种优秀MVC框架,不同 ...

随机推荐

  1. WPF 3D中多个模型如何设置某一个在最前?

    原文:WPF 3D中多个模型如何设置某一个在最前? 问题:我们的模型包括导入的3D solid模型和axis坐标轴模型,当模型旋转的时候,3D会将axis挡住. 期望:axis一直在最前面,不会被3D ...

  2. 分享一下Oracle 10g和Toad for Oracle的安装步骤

    三年前用过Oracle,单纯的“用过”,主要就是说对数据库的一些操作,还不包含创建一些存储过程之类的,所以对Oracle仅仅只是了解一点儿,因为当时那家公司里面,数据库里面的东西都是那些顾问负责的,再 ...

  3. python 教程 第四章、 控制流

    第四章. 控制流 控制语句后面要加冒号: 1)    if语句 if guess == number: print 'Congratulations, you guessed it.' # New b ...

  4. 键盘各键对应的编码值(key code)

    原文:键盘各键对应的编码值(key code) 来源:http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes ...

  5. WPF使用MediaElement显示gif图片

    原文:WPF使用MediaElement显示gif图片 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/SANYUNI/article/details ...

  6. js调查server

    <script type="text/javascript"> function showUnreadNews() { $(document).ready(functi ...

  7. AABB边框、OBB边框、通过比较球包围

    1) AABB 包围盒: AABB 包围盒是与坐标轴对齐的包围盒, 简单性好, 紧密性较差(尤其对斜对角方向放置的瘦长形对象, 採用AABB, 将留下非常大的边角空隙, 导致大量不是必需的包围盒相交測 ...

  8. AngularJS ng-if使用

    示例中,根据ng-if指令显示不同任务状态,以及判断任务是否可以操作 <div ng-app="NgifDemoApp" ng-controller="NgifDe ...

  9. JNDI(Java Naming and Directory Interface)

    # 前言 内容基本拷贝,整理出来,方便以后回忆. # What The Java Naming and Directory Interface™ (JNDI) is an application pr ...

  10. passed into methods by value java专题

    java没有引用传递只有按值传递,没有引用传递只有按值传递,值传递.因为Primitive类型的值不能改变,所以method不能更改调用方传的primitive 值.因为method更改的是Primi ...