SpringMVC

SpringMVC

image-20220726153114289

1.入门程序

1.1导入jar包:

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
<!-- 版本锁定 --> 
<properties>
<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>

1.2配置核心的控制器(配置DispatcherServlet)

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

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

1.3编写springmvc.xml的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
<?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">
<!-- 配置spring创建容器时要扫描的包 -->
<context:component-scan base-package="com.itheima"></context:component-scan>
<!-- 配置视图解析器 -->
<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>
<!-- 配置spring开启注解mvc的支持 <mvc:annotation-driven></mvc:annotation-driven>-->
</beans>

1.4编写index.jsp和HelloController控制器类

  1. index.jsp

    1
    2
    3
    4
    <body>
    <h3>入门案例</h3>
    <a href="${ pageContext.request.contextPath }/hello">入门案例</a>
    </body>
  2. HelloController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package cn.itcast.controller; 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/*** 控制器
* @author rt
*/
@Controller
public class HelloController {
/*** 接收请求
* @return
*/
@RequestMapping(path="/hello")
public String sayHello() {
System.out.println("Hello SpringMVC!!");
return "success";
}
}

1.5在WEB-INF目录下创建pages文件夹,编写success.jsp的成功页面

1
2
3
<body>
<h3>入门成功!!</h3>
</body>

1.6启动Tomcat服务器,进行测试

1.7SpringMVC 的请求响应流程

image-20220726153259992

2.RequestMapping 注解

作用:用于建立请求 URL 和处理请求方法之间的对应关系

出现位置:

​ 类上:请求 URL 的第一级访问目录。此处不写的话,就相当于应用的根目录。写的话需要以/开头。

它出现的目的是为了使我们的 URL 可以按照模块化管理:

​ 例如:

​ 账户模块:

/account/add

/account/update

/account/delete

​ 订单模块:

/order/add

/order/update

/order/delete

​ 红色的部分就是把 RequsetMappding 写在类上,使我们的 URL 更加精细。

​ 方法上:

​ 请求 URL 的第二级访问目录。

属性:

value:用于指定请求的 URL。它和 path 属性的作用是一样的。

method:用于指定请求的方式。

params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和配置的一模一样。

例如:

​ params = {“accountName”},表示请求参数必须有 accountName

​ params = {“moeny!100”},表示请求参数中 money 不能是 100。

headers:用于指定限制请求消息头的条件。

注意:

以上四个属性只要出现 2 个或以上时,他们的关系是与的关系。

举例:请求地址为/account/findAccount

1
2
3
4
5
6
7
8
9
10
11
12
13
控制器代码:
/**
* RequestMapping 注解出现的位置
*/
@Controller("accountController")
@RequestMapping("/account")
public class AccountController {

@RequestMapping("/findAccount")
public String findAccount() {
System.out.println("查询了账户。。。。");
return "success"; }
}

method 属性的示例:

1
2
3
4
5
6
7
8
9
/**
* 保存账户
* @return
*/
@RequestMapping(value="/saveAccount",method=RequestMethod.POST)
public String saveAccount() {
System.out.println("保存了账户");
return "success";
}

params 属性的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 删除账户
* @return
*/
@RequestMapping(value="/removeAccount",params= {"accountName","money>100"})
public String removeAccount() {
System.out.println("删除了账户");
return "success";
}
<a href="account/removeAccount?accountName=aaa&money>100">删除账户,金额 100</a>
<br/>
<a href="account/removeAccount?accountName=aaa&money>150">删除账户,金额 150</a>

当我们点击第一个超链接时,可以访问成功。
当我们点击第二个超链接时,无法访问。如下图:

image-20220726154310397

3 .请求参数的绑定

1
2
3
4
5
6
7
8
9
10
11
12
<a href="account/findAccount?accountId=10">查询账户</a>
中请求参数是:
accountId=10
/**
* 查询账户
* @return
*/
@RequestMapping("/findAccount")
public String findAccount(Integer accountId) {
System.out.println("查询了账户。。。。"+accountId);
return "success";
}

支持的数据类型:

基本类型参数:包括基本类型和 String 类型

POJO 类型参数:包括实体类,以及关联的实体类

数组和集合类型参数:包括 List 结构和 Map 结构的集合(包括数组)

SpringMVC 绑定请求参数是自动实现的,但是要想使用,必须遵循使用要求。

使用要求:

如果是基本类型或者 String 类型:

要求我们的参数名称必须和控制器中方法的形参名称保持一致。(严格区分大小写)

如果是 POJO 类型,或者它的关联对象:

要求表单中参数名称和 POJO 类的属性名称保持一致。并且控制器方法的参数类型是 POJO 类型。

如果是集合类型,有两种方式:

第一种:

​ 要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同。

​ 给 List 集合中的元素赋值,使用下标。

​ 给 Map 集合中的元素赋值,使用键值对。

第二种:

​ 接收的请求参数是 json 格式数据。需要借助一个注解实现。

3.1基本类型和 String 类型作为参数

1
2
3
4
5
6
7
8
9
10
11
12
13
jsp 代码:
<!-- 基本类型示例 -->
<a href="account/findAccount?accountId=10&accountName=zhangsan">查询账户</a>
控制器代码:
/**
* 查询账户
* @return
*/
@RequestMapping("/findAccount")
public String findAccount(Integer accountId,String accountName) {
System.out.println("查询了账户。。。。"+accountId+","+accountName);
return "success";
}

3.2POJO 类型作为参数

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
实体类代码:
/**
* 账户信息
*/
public class Account implements Serializable {
private Integer id;
private String name;
private Float money;
private Address address;
//getters and setters
}
/**
* 地址的实体类
*/
public class Address implements Serializable {
private String provinceName;
private String cityName;
//getters and setters
}

jsp 代码:
<!-- pojo 类型演示 -->
<form action="account/saveAccount" method="post">
账户名称:<input type="text" name="name" ><br/>
账户金额:<input type="text" name="money" ><br/>
账户省份:<input type="text" name="address.provinceName" ><br/>
账户城市:<input type="text" name="address.cityName" ><br/>
<input type="submit" value="保存">
</form>

控制器代码:
/**
* 保存账户
* @param account
* @return
*/
@RequestMapping("/saveAccount")
public String saveAccount(Account account) {
System.out.println("保存了账户。。。。"+account);
return "success";
}

3.3POJO 类中包含集合类型参数

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
实体类代码:
/**
* 用户实体类
*/
public class User implements Serializable {
private String username;
private String password;
private Integer age;
private List<Account> accounts;
private Map<String,Account> accountMap;
//getters and setters
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + ", age="+ age + ",\n accounts=" + accounts+ ",\n accountMap=" + accountMap + "]";
}
}

jsp 代码:
<!-- POJO 类包含集合类型演示 -->
<form action="account/updateAccount" method="post">
用户名称:<input type="text" name="username" ><br/>
用户密码:<input type="password" name="password" ><br/>
用户年龄:<input type="text" name="age" ><br/>
账户 1 名称:<input type="text" name="accounts[0].name" ><br/>
账户 1 金额:<input type="text" name="accounts[0].money" ><br/>
账户 2 名称:<input type="text" name="accounts[1].name" ><br/>
账户 2 金额:<input type="text" name="accounts[1].money" ><br/>
账户 3 名称:<input type="text" name="accountMap['one'].name" ><br/>
账户 3 金额:<input type="text" name="accountMap['one'].money" ><br/>
账户 4 名称:<input type="text" name="accountMap['two'].name" ><br/>
账户 4 金额:<input type="text" name="accountMap['two'].money" ><br/>
<input type="submit" value="保存">
</form>

控制器代码:
/**
* 更新账户
* @return
*/
@RequestMapping("/updateAccount")
public String updateAccount(User user) {
System.out.println("更新了账户。。。。"+user);
return "success";
}

image-20220726155252399

3.4自定义类型转换器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 特殊情况之:类型转换问题 --> 
<a href="account/deleteAccount?date=2018-01-01">根据日期删除账户</a>

控制器代码:
/**
* 删除账户
* @return
*/
@RequestMapping("/deleteAccount")
public String deleteAccount(String date) {
System.out.println("删除了账户。。。。"+date);
return "success";
}
运行结果

image-20220726155503573

1
2
3
4
5
6
7
8
9
10
11
当我们把控制器中方法参数的类型改为 Date 时
/**
* 删除账户
* @return
*/
@RequestMapping("/deleteAccount")
public String deleteAccount(Date date) {
System.out.println("删除了账户。。。。"+date);
return "success";
}
运行结果:

image-20220726155603324

3.4.1使用步骤

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
第一步:定义一个类,实现 Converter 接口,该接口有两个泛型。
public interface Converter<S, T> {//S:表示接受的类型,T:表示目标类型
/**
* 实现类型转换的方法
*/
@Nullable
T convert(S source);
}
/**
* 自定义类型转换器
*/
public class StringToDateConverter implements Converter<String, Date> {
/**
* 用于把 String 类型转成日期类型
*/
@Override
public Date convert(String source) {
DateFormat format = null;
try {
if(StringUtils.isEmpty(source)) {
throw new NullPointerException("请输入要转换的日期");
}
format = new SimpleDateFormat("yyyy-MM-dd");
Date date = format.parse(source);
return date;
} catch (Exception e) {
throw new RuntimeException("输入日期有误");
}
}
}

第二步:在 spring 配置文件中配置类型转换器。

spring 配置类型转换器的机制是,将自定义的转换器注册到类型转换服务中去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 配置类型转换器工厂 --> 
<bean id="converterService"class="org.springframework.context.support.ConversionServiceFactoryBean">
<!-- 给工厂注入一个新的类型转换器 -->
<property name="converters">
<array>
<!-- 配置自定义类型转换器 -->
<bean class="com.itheima.web.converter.StringToDateConverter"></bean>
</array>
</property>
</bean>
第三步:在 annotation-driven 标签中引用配置的类型转换服务
<!-- 引用自定义类型转换器 -->
<mvc:annotation-driven
conversion-service="converterService"></mvc:annotation-driven>

4常用注解

4.1RequestParam

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

属性:value:请求参数中的名称。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
jsp 中的代码:
<!-- requestParams 注解的使用 -->
<a href="springmvc/useRequestParam?name=test">requestParam 注解</a>
控制器中的代码:
/**
* requestParams 注解的使用
* @param username
* @return
*/
@RequestMapping("/useRequestParam")
public String useRequestParam(@RequestParam("name")String username,@RequestParam(value="age",required=false)Integer age){
System.out.println(username+","+age);
return "success";
}

4.2RequestBody

作用:用于获取请求体内容。直接使用得到是 key=value&key=value…结构的数据。

get 请求方式不适用。

属性:required:是否必须有请求体。默认值是:true。当取值为 true 时,get 请求方式会报错。如果取值为 false,get 请求得到是 null。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
post 请求 jsp 代码:
<!-- request body 注解 -->
<form action="springmvc/useRequestBody" method="post">
用户名称:<input type="text" name="username" ><br/>
用户密码:<input type="password" name="password" ><br/>
用户年龄:<input type="text" name="age" ><br/>
<input type="submit" value="保存">
</form>

get 请求 jsp 代码:
<a href="springmvc/useRequestBody?body=test">requestBody 注解 get 请求</a>

控制器代码:
/**
* RequestBody 注解
* @param user
* @return
*/
@RequestMapping("/useRequestBody")
public String useRequestBody(@RequestBody(required=false) String body){
System.out.println(body);
return "success";
}

image-20220726161514463

4.3PathVaribale

作用:

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

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

属性:

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
jsp 代码:
<!-- PathVariable 注解 -->
<a href="springmvc/usePathVariable/100">pathVariable 注解</a>

控制器代码:
/**
* PathVariable 注解
* @param user
* @return
*/
@RequestMapping("/usePathVariable/{id}")
public String usePathVariable(@PathVariable("id") Integer id){
System.out.println(id);
return "success";
}

4.4RequestHeader

作用:

用于获取请求消息头。

属性:

value:提供消息头名称

required:是否必须有此消息头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
jsp 中代码:
<!-- RequestHeader 注解 -->
<a href="springmvc/useRequestHeader">获取请求消息头</a>

控制器中代码:
/**
* RequestHeader 注解
* @param user
* @return
*/
@RequestMapping("/useRequestHeader")
public String useRequestHeader(@RequestHeader(value="Accept-Language",required=false)String requestHeader){
System.out.println(requestHeader);
return "success";
}

4.5CookieValue

作用:

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

属性:

value:指定 cookie 的名称。

required:是否必须有此 cookie。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
jsp 中的代码:
<!-- CookieValue 注解 -->
<a href="springmvc/useCookieValue">绑定 cookie 的值</a>

控制器中的代码:
/**
* Cookie 注解注解
* @param user
* @return
*/
@RequestMapping("/useCookieValue")
public String useCookieValue(@CookieValue(value="JSESSIONID",required=false) String cookieValue){
System.out.println(cookieValue);
return "success";
}

4.6ModelAttribute

作用:

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

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

以修饰有具体返回值的方法。

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

属性:

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

应用场景:

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

例如:

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

4.6.1 基于 POJO 属性的基本使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
jps 代码:
<!-- ModelAttribute 注解的基本使用 -->
<a href="springmvc/testModelAttribute?username=test">测试 modelattribute</a>

控制器代码:
/**
* 被 ModelAttribute 修饰的方法
* @param user
*/
@ModelAttribute
public void showModel(User user) {
System.out.println("执行了 showModel 方法"+user.getUsername());
}
/**
* 接收请求的方法
* @param user
* @return
*/
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user) {
System.out.println("执行了控制器的方法"+user.getUsername());
return "success";
}

image-20220726163537585

4.6.2 基于 Map 的应用场景示例

ModelAttribute 修饰方法带返回值

需求:
修改用户信息,要求用户的密码不能修改

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
jsp 的代码:
<!-- 修改用户信息 -->
<form action="springmvc/updateUser" method="post">
用户名称:<input type="text" name="username" ><br/>
用户年龄:<input type="text" name="age" ><br/>
<input type="submit" value="保存">
</form>

控制的代码:
/**
* 查询数据库中用户信息
* @param user
*/
@ModelAttribute
public User showModel(String username) {
//模拟去数据库查询
User abc = findUserByName(username);
System.out.println("执行了 showModel 方法"+abc);
return abc;
}
/**
* 模拟修改用户方法
* @param user
* @return
*/
@RequestMapping("/updateUser")
public String testModelAttribute(User user) {
System.out.println("控制器中处理请求的方法:修改用户:"+user);
return "success";
}

/**
* 模拟去数据库查询
* @param username
* @return
*/
private User findUserByName(String username) {
User user = new User();
user.setUsername(username);
user.setAge(19);
user.setPassword("123456");
return user;
}

image-20220726164147345

ModelAttribute 修饰方法不带返回值

需求:
修改用户信息,要求用户的密码不能修改

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
jsp 中的代码:
<!-- 修改用户信息 -->
<form action="springmvc/updateUser" method="post">
用户名称:<input type="text" name="username" ><br/>
用户年龄:<input type="text" name="age" ><br/>
<input type="submit" value="保存">
</form>

控制器中的代码:
/**
* 查询数据库中用户信息
* @param user
*/
@ModelAttribute
public void showModel(String username,Map<String,User> map) {
//模拟去数据库查询
User user = findUserByName(username);
System.out.println("执行了 showModel 方法"+user);
map.put("abc",user);
}
/**
* 模拟修改用户方法
* @param user
* @return
*/
@RequestMapping("/updateUser")
public String testModelAttribute(@ModelAttribute("abc")User user) {
System.out.println("控制器中处理请求的方法:修改用户:"+user);
return "success";
}
/**
* 模拟去数据库查询
* @param username
* @return
*/
private User findUserByName(String username) {
User user = new User();
user.setUsername(username);
user.setAge(19);
user.setPassword("123456");
return user;
}

image-20220726164407981

4.7SessionAttribute

作用:

用于多次执行控制器方法间的参数共享。

属性:

value:用于指定存入的属性名称

type:用于指定存入的数据类型。

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
jsp 中的代码:
<!-- SessionAttribute 注解的使用 -->
<a href="springmvc/testPut">存入 SessionAttribute</a> <hr/>
<a href="springmvc/testGet">取出 SessionAttribute</a> <hr/>
<a href="springmvc/testClean">清除 SessionAttribute</a>

控制器中的代码:
/**
* SessionAttribute 注解的使用
*/
@Controller("sessionAttributeController")
@RequestMapping("/springmvc")
@SessionAttributes(value ={"username","password"},types={Integer.class})
public class SessionAttributeController {
/**
* 把数据存入 SessionAttribute
* @param model
* @return
* Model 是 spring 提供的一个接口,该接口有一个实现类 ExtendedModelMap
* 该类继承了 ModelMap,而 ModelMap 就是 LinkedHashMap 子类
*/
@RequestMapping("/testPut")
public String testPut(Model model){
model.addAttribute("username", "泰斯特");
model.addAttribute("password","123456");
model.addAttribute("age", 31);
//跳转之前将数据保存到 username、password 和 age 中,因为注解@SessionAttribute 中有这几个参数
return "success";
}
@RequestMapping("/testGet")
public String testGet(ModelMap model){
System.out.println(model.get("username")+";"+model.get("password")+";"+model.get("a
ge"));
return "success";
}

@RequestMapping("/testClean")
public String complete(SessionStatus sessionStatus){
sessionStatus.setComplete();
return "success";
}
}

image-20220726164952488

5.响应数据和结果视图

5.1返回值分类

字符串

1
2
3
4
5
@RequestMapping("/testReturnString")
public String testReturnString() {
System.out.println("AccountController 的 testReturnString 方法执行了。。。。");
return "success";
}

void

1
2
3
4
@RequestMapping("/testReturnVoid")
public void testReturnVoid(HttpServletRequest request,HttpServletResponse response)
throws Exception {
}

在 controller 方法形参上可以定义 request 和 response,使用 request 或 response 指定响应结果:

1、使用 request 转向页面,如下:

1
request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response);

2、也可以通过 response 页面重定向:

1
response.sendRedirect("testRetrunString")

3、也可以通过response 指定响应结果,例如响应 json 数据:

1
2
3
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json 串");

ModelAndView

ModelAndView 是 SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值。

image-20220726170015531

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
示例代码:
/**
* 返回 ModeAndView
* @return
*/
@RequestMapping("/testReturnModelAndView")
public ModelAndView testReturnModelAndView() {
ModelAndView mv = new ModelAndView();
mv.addObject("username", "张三");
mv.setViewName("success");
return mv;
}

响应的 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>执行成功</title>
</head>
<body>
执行成功!
${requestScope.username}
</body>
</html>

image-20220726170210724

5.2转发和重定向

forward 转发

1
2
3
4
5
6
7
8
9
10
11
12
13
controller 方法在提供了 String 类型的返回值之后,默认就是请求转发。我们也可以写成:
/**
* 转发
* @return
*/
@RequestMapping("/testForward")
public String testForward() {
System.out.println("AccountController 的 testForward 方法执行了。。。。");
return "forward:/WEB-INF/pages/success.jsp";
}
需要注意的是,如果用了 formward:则路径必须写成实际视图 url,不能写逻辑视图。
它相当于“request.getRequestDispatcher("url").forward(request,response)”。使用请求
转发,既可以转发到 jsp,也可以转发到其他的控制器方法。

Redirect 重定向

1
2
3
4
5
6
7
8
9
10
11
12
contrller 方法提供了一个 String 类型返回值之后,它需要在返回值里使用:redirect:
/**
* 重定向
* @return
*/
@RequestMapping("/testRedirect")
public String testRedirect() {
System.out.println("AccountController 的 testRedirect 方法执行了。。。。");
return "redirect:testReturnModelAndView";
}
它相当于“response.sendRedirect(url)”。需要注意的是,如果是重定向到 jsp 页面,则 jsp 页面不
能写在 WEB-INF 目录中,否则无法找到。

5.3ResponseBody 响应 json 数据

作用:

该注解用于将 Controller 的方法返回的对象,通过 HttpMessageConverter 接口转换为指定格式的数据如:json,xml 等,通过 Response 响应给客户端

需求:

使用@ResponseBody 注解实现将 controller 方法返回对象转换为 json 响应给客户端。

前置知识点:

Springmvc 默认用 MappingJacksonHttpMessageConverter 对 json 数据进行转换,需要加入jackson 的包。

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
jsp 中的代码:
<script type="text/javascript"
src="${pageContext.request.contextPath}/js/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$("#testJson").click(function(){
$.ajax({
type:"post",
url:"${pageContext.request.contextPath}/testResponseJson",
contentType:"application/json;charset=utf-8",
data:'{"id":1,"name":"test","money":999.0}',
dataType:"json",
success:function(data){
alert(data);
}
});
});
})
</script>
<!-- 测试异步请求 -->
<input type="button" value="测试 ajax 请求 json 和响应 json" id="testJson"/>

控制器中的代码:
/**
* 响应 json 数据的控制器
*/
@Controller("jsonController")
public class JsonController {
/**
* 测试响应 json 数据
*/
@RequestMapping("/testResponseJson")
public @ResponseBody Account testResponseJson(@RequestBody Account account) {
System.out.println("异步请求:"+account);
return account;
}
}

SpringMVC
http://example.com/2022/07/23/SpringMVC/
作者
Deng ErPu
发布于
2022年7月23日
许可协议