例子中很多都是接口形式的,虽然案例中使用的是html发送请求的方式,但是还是更推荐使用postman来调试,会方便许多。
一、基本概念
1.1 三层架构
我们的开发模式,一般都是基于两种形式,一种是C/S架构,也就是客户端/服务器;另一种是B/S架构,也就是浏览器/服务器。
在JavaEE开发中,几乎全都是基于B/S架构的开发。在B/S架构中,系统标准的三层架构包括:表现层、业务层、持久层。
- 表现层:如SpringMVC。负责接收客户端的请求、向客户端响应结果。表现层包括展示层和控制层。
- 业务层:如Spring。也就是service层,负责业务逻辑处理,表现层依赖业务层,业务层并不依赖表现层。
- 持久层:如Mybatis、Hibernate。
1.2 MVC模型
MVC全名是Model View Controller,是模型-视图-控制器的缩写,是一种用于设计创建web应用程序表现层的模式。MVC中每个部分各司其职
- Model模型:通常指的是数据模型。一般情况下用于封装数据。
- View视图:如html。展示数据,视图通常是依据数据模型来创建的。
- Controller控制器:应用程序中处理用户交互的部分。作用一般就是处理程序逻辑的。
1.3 SpringMVC
SpringMVC是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架,是目前最主流的MVC框架之一。同样的MVC框架还有structs2。支持RestFul编程风格。
优势
- 清晰的角色划分
- 前端控制器DispatcherServlet
- 请求到处理器映射HandlerMapping
- 处理器适配器HandlerAdapter
- 视图解析器ViewResolver
- 处理器或页面控制器Controller
- 验证器Validator
- 命令对象Command(请求参数绑定到的对象就叫命令对象)
- 表单对象FormObject(提供给表单展示和提交到的对象叫表单对象)
- 命令对象就是一个pojo,直接就能作为业务对象
- SpringMVC基于组件的方式执行流程
1.4 restful编程
对比这张图里,就能大概了解restful是个啥意思了。
传统的编程中,控制器里面,save、findAll、update会支持各种请求方法,创建三个接口。
restful编程中,控制器里面只需要提供一个接口,接口按照不同的请求方式执行不同的操作。
restful编程参考RESTful API 设计指南 - 阮一峰的网络日志,如果你用了屏蔽广告插件导致内容无法显示,直接将其域名的js权限禁用掉就ok。
对于资源的具体操作类型,由HTTP动词表示。
常用的HTTP动词有下面五个(括号里是对应的SQL命令)。
- GET(SELECT):从服务器取出资源(一项或多项)。
- POST(CREATE):在服务器新建一个资源。
- PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
- PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
- DELETE(DELETE):从服务器删除资源。
还有两个不常用的HTTP动词。
- HEAD:获取资源的元数据。
- OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。
下面是一些例子。
- GET /zoos:列出所有动物园
- POST /zoos:新建一个动物园
- GET /zoos/ID:获取某个指定动物园的信息
- PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
- PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
- DELETE /zoos/ID:删除某个动物园
- GET /zoos/ID/animals:列出某个指定动物园的所有动物
- DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物
二、入门
2.1 实现
需求
- index.jsp发送请求
- 转发到success.jsp成功页面
步骤
- 搭建开发环境:使用maven提供的骨架搭建webapp
- 编写程序
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| <?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>top.meethigher</groupId> <artifactId>SpringMvc</artifactId> <version>1.0</version> <packaging>war</packaging>
<name>SpringMvc Maven Webapp</name> <url>http://www.example.com</url>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <spring.version>5.0.2.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.0</version> <scope>provided</scope> </dependency> </dependencies>
<build> <finalName>SpringMvc</finalName> <pluginManagement> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
|
web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>dispacherServlet</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>dispacherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
|
springmvc.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="top.meethigher"/> <mvc:annotation-driven/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"></property> <property name="suffix" value=".jsp"></property> </bean> </beans>
|
index.jsp
1 2 3 4 5 6 7 8 9 10
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h3>入门程序</h3> <a href="/hello">入门程序</a> </body> </html>
|
success.jsp
1 2 3 4 5 6 7 8 9
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h3>入门成功</h3> </body> </html>
|
HelloController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Controller public class HelloController {
public HelloController() { System.out.println("启动"); }
@RequestMapping("/hello") public String sayHello(){ System.out.println("Hello MVC"); return "success"; } }
|
访问的hello,实际是转发请求到了success.jsp
2.2 原理
由于配置了dispatcherServlet为项目启动时就进行加载,所以像springmvc.xml,以及创建扫描的类和视图解析器的对象。
可以在添加了注解并且要进行扫描的类中,在默认构造方法中打印日志来验证,不同的配置的执行顺序。
dispatcherServlet主要体现在他的控制作用,客户端的请求过来,首先被dispatcherServlet捕获,然后将请求转发到对应的控制器中获取到返回值,根据这个返回值,通过视图解析器,解析到对应的结果视图。将返回内容返给客户端。
2.3 组件详解
DispatcherServlet:前端控制器
DispatcherServlet是整个流程控制的中心,由他来调用其他组件处理用户的请求,同时,也降低了组件之间的耦合性。
HandlerMapping:处理器映射器
HandlerMapping负责根据用户请求找到请求适配器HandlerAdapter。
HandlerAdapter:处理器适配器
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用。通过扩展适配器可以对更多类型的处理器进行执行。
Handler:处理器
开发中要编写的具体业务控制器。由DispatcherServlet把用户请求转发到Handler,由Handler对具体的用户进行请求处理。
ViewResolver:视图解析器
View Resolver负责将处理结果生成view视图。View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
View:视图
SpringMVC提供了很多view视图的支持,像jstlView、freemarkerview、pdfView。
2.4 RequestMapping
通过阅读源码可知,@RequestMapping
既可以放在类上也可以放在方法上。并且其中的value
与path
作用是相同的。
如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略
如果在类上加了@RequestMapping
注解,并且配置了value
,那么,方法中所有的通过@RequestMapping
配置的路径,都在类的value
的路径之下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Controller @RequestMapping("/hh") public class HelloController {
public HelloController() { System.out.println("启动"); }
@RequestMapping(value = "/hello",method = {RequestMethod.DELETE,RequestMethod.GET},params = {"name","age"},headers = "aaa") public String sayHello(){ System.out.println("Hello MVC"); return "success"; } }
|
上面代码,访问sayHello
方法时,就需要通过/hh/hello
来访问。
method属性表示访问的请求方式。上述代码只能通过Delete、Get请求访问。
params属性用于指定限制请求参数的条件,必传的名称可以放入到params里面。上述代码必须携带name、age参数。
headers属性用于限制请求头的条件,必传的名称放入headers里面。
三、参数绑定
参数绑定通俗点说,就是获取参数。类似于Servlet通过getParameter获取参数。
基本参数
如果接收的参数是基本类型,可以直接通过在controller中写方法,就能自动接收了。
发送请求
1
| <a href="hh/param?name=hh&age=20">入门程序</a>
|
获取参数
1 2 3 4 5 6 7 8 9
| @Controller @RequestMapping("/hh") public class HelloController { @RequestMapping(value="/param") public String getParam(String name,String age){ System.out.println("name="+name+",age="+age); return "success"; } }
|
实体参数
属性为基本或实体类型
如果是实体参数内部都是基本属性,可以直接在控制器方法中写对应实体,直接接收。
如果是实体参数内部嵌套了实体属性,就需要在发送时用对象属性.属性
来发送请求,控制器那边直接写实体接收即可。
发送请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h3>入门程序</h3> <a href="hh/param?name=hh&age=20">入门程序</a> <h3>造钱</h3> <form action="/hh/money" method="post"> <input name="money" placeholder="钱"> <button type="submit">submit</button> </form> <h3>造人</h3> <form action="/hh/person" method="post"> <input name="name" placeholder="名"> <input name="age" placeholder="年龄"> <input name="money.money" placeholder="钱"> <button type="submit">submit</button> </form> </body> </html>
|
控制器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| @Controller @RequestMapping("/hh") public class HelloController {
@RequestMapping(value="/money") public String getMoney(Money money){ System.out.println(money); return "success"; }
@RequestMapping(value="/person") public String getPerson(Person person){ System.out.println(person); return "success"; } }
|
在post请求时,会出现后端获取中文出现乱码的情况。
如果是在Servlet中时,我们需要通过request.setCharacterEncoding(“utf-8”)来解决。
在Spring中,提供了类似的方法,需要在配置文件中配置过滤器
web.xml配置如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>dispacherServlet</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>dispacherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
<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> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
|
通过阅读filter-class源码,我们可以知道其实本质上,它也是走的request.setCharacterEncoding这个方式。
属性为集合类型
直接看例子吧。
请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <%-- Created by IntelliJ IDEA. User: meethigher Date: 2021/8/22 Time: 21:29 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h3>List与Map</h3> <form action="/hh/people" method="post"> <input name="personList[0].name" placeholder="名"/> <input name="personList[0].age" placeholder="年龄"/> <input name="personList[0].money.money" placeholder="钱"/> <input name="personList[1].name" placeholder="名"/> <input name="personList[1].age" placeholder="年龄"> <input name="personList[1].money.money" placeholder="钱">
<input name="personMap['first'].name" placeholder="名"/> <input name="personMap['first'].age" placeholder="年龄"/> <input name="personMap['first'].money.money" placeholder="钱"/> <input name="personMap['second'].name" placeholder="名"/> <input name="personMap['second'].age" placeholder="年龄"> <input name="personMap['second'].money.money" placeholder="钱"> <button type="submit">submit</button> </form> </body> </html>
|
控制器
1 2 3 4 5 6 7 8 9 10
| @Controller @RequestMapping("/hh") public class HelloController {
@RequestMapping(value="/people") public String getList(People people){ System.out.println(people); return "success"; } }
|
自定义类型转换器
Spring提供的转换器都实现了Convertor这个接口,所以如果我们要实现自定义类型转换器的话,也需要实现该接口。
Convertor的两个泛型,前面指的是源类型、后面指的是目标类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class StringToDateConverter implements Converter<String, Date> { @Override public Date convert(String source) { if (ObjectUtils.isEmpty(source)) { throw new RuntimeException("必须传入数据!"); } SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); try { return sdf.parse(source); } catch (ParseException e) { throw new RuntimeException("必须传入数据!格式yyyy-MM-dd"); } } }
|
springmvc.xml配置添加自定义转换器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="top.meethigher"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"></property> <property name="suffix" value=".jsp"></property> </bean>
<bean id="customConversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="top.meethigher.controller.StringToDateConverter"/> </set> </property> </bean>
<mvc:annotation-driven conversion-service="customConversionService"/> </beans>
|
发送请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h3>创建一只狗</h3> <form action="/hh/dog" method="post"> <input name="name" placeholder="名"> <input name="birth" placeholder="生日"> <button type="submit">submit</button> </form> </body> </html>
|
控制器
1 2 3 4 5 6 7 8 9
| @Controller @RequestMapping("/hh") public class HelloController { @RequestMapping(value = "/dog") public String getDog(Dog dog) { System.out.println(dog); return "success"; } }
|
获取Servlet原生API
如果想要获取servlet的request,那就直接在控制器方法中加HttpServletRequest。
如果想要获取servlet的response,那就直接在控制器方法中加HttpServletResponse。
发送请求
1
| <a href="/hh/api">servletAPI</a>
|
控制器
1 2 3 4 5 6 7 8 9 10 11 12
| @Controller @RequestMapping("/hh") public class HelloController { @RequestMapping(value = "/api") public String getApi(HttpServletRequest request, HttpServletResponse response) { System.out.println(request); System.out.println(response); System.out.println(request.getSession()); System.out.println(request.getSession().getServletContext()); return "success"; } }
|
四、常用注解
4.1 RequestParam
作用
把请求中的指定参数,给控制器方法中参数赋值
属性
- value:请求的参数名称
- required:请求参数中此参数是否必传。默认值true
请求
1
| <a href="/testRequestParam?username=ccc">requestParam</a>
|
控制器
1 2 3 4 5 6 7 8 9
| @Controller public class AnnotationController {
@RequestMapping("/testRequestParam") public String testRequestParam(@RequestParam(value="username") String username1) { System.out.println(username1); return "success"; } }
|
如果不加@RequestParam,那么调用该接口时,没有对应的username属性来接收内容,输出为空。
如果加了@RequestParam,里面默认的required=true,那么调用该接口时,如果传值不对,会报错。
4.2 RequestBody
作用
get请求方式不适用。
用于获取请求体内容。直接使用,获取到的字符串是key=value&key=value的结构的数据。
属性
- required:是否必须有请求体,默认为true
请求
1 2 3 4 5 6
| <form action="/testRequestBody" method="post"> <input name="name" placeholder="名"> <input name="age" placeholder="年龄"> <input name="money.money" placeholder="钱"> <button type="submit">submit</button> </form>
|
控制器
1 2 3 4 5 6 7 8
| @Controller public class AnnotationController { @RequestMapping("/testRequestBody") public String testRequestBody(@RequestBody String body) { System.out.println(body); return "success"; } }
|
4.3 PathVariable
@PathVariable接收两个参数
作用
绑定url中的占位符。例如/findById/{id},这个{id}就是url中的占位符。
url支持占位符是spring3.0之后加入的,是springmvc支持rest风格url的一个重要标志。参考1.4。
属性
- value:url中占位符名称
- required:是否必须提供占位符
发送请求
1
| <a href="/testPathVariable/ccc">pathVariable</a>
|
控制器
1 2 3 4 5
| @RequestMapping("/testPathVariable/{id}") public String testPathVariable(@PathVariable(value = "id") String id) { System.out.println(id); return "success"; }
|
注意事项
因为form表单只支持get、post请求,所以如果想要使用restful的话,那么就需要用到别的请求方式。这边SpringMVC提供了HiddenHttpMethodFilter过滤器,参考文章Spring MVC过滤器-HiddenHttpMethodFilter - 一个坚果 - 博客园
作用
获取请求消息头
属性
- value:提供消息头名称
- required:是否必须有此消息头
没啥用,就是获取请求头,倒不如用Servlet原生api
1 2 3 4 5 6
| @RequestMapping("/testPathVariable/{id}") public String testPathVariable(@PathVariable(value = "id") String id, @RequestHeader("User-Agent") String userAgent) { System.out.println(id); System.out.println(userAgent); return "success"; }
|
4.5 CookieValue
作用
获取指定名称cookie
属性
- value:指定cookie名称
- required:是否必须有该Cookie
没啥用,就是获取请求头,倒不如用Servlet原生api
1 2 3 4 5 6 7
| @RequestMapping("/testPathVariable/{id}") public String testPathVariable(@PathVariable(value = "id") String id, @RequestHeader("User-Agent") String userAgent,@CookieValue("JSESSIONID") String session) { System.out.println(id); System.out.println(userAgent); System.out.println(session); return "success"; }
|
4.5 ModelAttribute
作用
- 放在方法上,表示当前方法会在控制器的方法执行前先执行。它可以修饰没有返回值的方法,也可以修改有具体返回值的方法。
- 放在参数上,获取指定的参数给数据赋值。
应用场景
- 当前端的表单提交数据,无法获取和提交完整的数据时,可以通过@ModelAttribute通过数据库补全缺少的数据。比如,前端在执行变更时,只需要传递过来要变更的id,以及要修改的字段内容,后台通过@ModelAttribute来补全未变更的数据,之后直接保存对象到数据库里。
没有特定条件的@ModelAttribute会在所有控制器的方法执行前执行
如:
1 2 3 4
| @ModelAttribute public void showMsg(){ System.out.println("@ModelAttribute执行"); }
|
如果想要让控制器的方法获取到@ModelAttribute返回的对象,有两种方式
法一:@ModelAttribute修饰的方法带有返回值
1 2 3 4 5 6 7 8 9 10 11
| @RequestMapping("/testDog") public String testDog(Dog dog) { System.out.println(dog); return "success"; } @ModelAttribute public Dog modelAttribute(@RequestParam(value = "username1") String username1) { System.out.println("modelAttribute执行了"); System.out.println(username1); return new Dog("aaa", new Date()); }
|
上面这个例子,如果要访问testDog接口,会先访问modelAttribute方法,并且要求必传username1,然后再执行testDog方法。
如果传了username1
,又传了Dog对象,那么username1
就只是作为一个必传的入参了,优先级没有直接传入的Dog对象优先级高。
法二:@ModelAttribute修饰的方法不带返回值
1 2 3 4 5 6 7 8 9 10 11
| @RequestMapping("/testDog") public String testDog(@ModelAttribute("dog") Dog dog) { System.out.println(dog); return "success"; } @ModelAttribute public void modelAttribute(@RequestParam(value = "username1") String username1, Map<String, Dog> map) { System.out.println("modelAttribute执行了"); System.out.println(username1); map.put("dog", new Dog("aaa", new Date())); }
|
最终的效果其实跟法一是一样的。并没有因为换了方法优先级就高了之类。
4.6 SessionAttribute
作用
用于多次执行控制器方法间的参数在Session间共享。
属性
- value:存入的属性名称
- type:存入的数据类型
success.jsp
1 2 3 4 5 6 7 8 9 10
| <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <h3>入门成功</h3> ${requestScope.msg} </body> </html>
|
Controller中方法
1 2 3 4 5 6 7
| @RequestMapping("/testSession") public String testSession(Model model){ System.out.println("测试SessionAttributes注解"); model.addAttribute("msg","彩麟yyds"); return "success"; }
|
Model是存储在RequestScope中的,如果想要存到SessionScope,需要通过@SessionAttributes。
查看@SessionAttributes源码,可知该注解只能作用于类上。
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface SessionAttributes { @AliasFor("names") String[] value() default {};
@AliasFor("value") String[] names() default {};
Class<?>[] types() default {}; }
|
通过@SessionAttributes将RequestScope中的msg存入到SessionScope中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Controller @SessionAttributes(value = "msg") public class AnnotationController { @RequestMapping("/testSession") public String testSession(Model model){ System.out.println("测试SessionAttributes注解"); model.addAttribute("msg","彩麟yyds"); return "success"; }
@RequestMapping("/getMsg") public String getMsg(ModelMap modelMap){ System.out.println(modelMap.get("msg")); return "success"; }
@RequestMapping("/delMsg") public String delMsg(SessionStatus status){ status.setComplete(); return "success"; } }
|
4.7 ResponseBody
@ResponseBody作用于方法上,表示该方法的返回结果直接写入到响应中,一般用于前端异步获取数据时,也就是接口。
@RestController=@Controller+@ResponseBody
@Controller可以返回到指定的jsp、html等模板引擎页面
springBoot的转发和重定向_anjunshuang-CSDN博客_springboot转发