SpringMVC 入门、请求、响应
SpringMVC 概述
SSM 简介
SSM 三层架构
-
表现层:负责数据展示
-
业务层:负责业务处理
-
数据层:负责数据操作
MVC 简介
MVC(Model View Controller)是一种用于设计及创建 Web 应用程序表现层的模式。
-
Model(模型):数据模型,用于封装数据
-
View(视图):页面视图,用于展示数据
- jsp
- html
-
Controller(控制器):处理用户交互的调度器,用于根据用户需求处理程序逻辑
- Servlet
- SpringMVC
SpringMVC 简介
SpringMVC 是一种基于 Java 实现的、MVC 模型的、轻量级的 Web 框架。
SpringMVC 优点:
- 使用简单
- 性能突出(相比现有的框架技术)
- 灵活性强
入门案例
SpringMVC 工作流程分析:
- 服务器启动:
- 加载 web.xml 中 DispatcherServlet;
- 读取 spring-mvc.xml 中的配置,加载所有 com 包中所有标记为 bean 的类;
- 读取 bean 中方法上方标注 @RequestMapping 的内容;
- 处理请求:
- DispatcherServlet 配置拦截所有请求“/”;
- 使用请求路径与所有加载的 @RequestMapping 的内容进行比对;
- 执行对应的方法;
- 根据方法的返回值在 webapp 目录中查找对应的页面并展示。
实现示例:
- 导入 SpringMVC 相关的 Maven 依赖:
<!-- servlet3.1规范的坐标 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--jsp坐标-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<!--spring的坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--spring web的坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--springmvc的坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
- 定义表现层处理器 Controller(等同于 Servlet),并配置成 Spring 的 bean:
@Controller
public class UserController {
public void save(){
System.out.println("user mvc controller is running ...");
}
}
- 定义 SpringMVC 配置文件(格式与 Spring 配置文件一致):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--扫描加载所有的控制类类-->
<context:component-scan base-package="com"/>
</beans>
- web.xml 中配置 SpringMVC 核心控制器,用于将请求转发到对应的具体业务处理器 Controller 中(等同于 Servlet 配置):
<servlet>
<servlet-name>DispatcherServlet</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>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
- 设定具体 Controller 的访问路径与返回页面(等同于 Servlet 在 web.xml 中的配置):
// 设定当前方法的访问映射地址
@RequestMapping("/save")
// 设置当前方法返回值类型为String,用于指定请求完成后跳转的页面
public String save(){
System.out.println("user mvc controller is running ...");
// 设定具体跳转的页面
return "success.jsp";
}
Spring 技术架构
DispatcherServlet(前端控制器)
:是整体流程控制的中心,由其调用其它组件处理用户的请求,有效降低了组件间的耦合性。- HandlerMapping(处理器映射器):负责根据用户请求找到对应具体的 Handler 处理器。
Handler(处理器)
:业务处理的核心类,通常由开发者编写,描述具体的业务。- HandlAdapter(处理器适配器):通过它对处理器进行执行。
- View Resolver(视图解析器):将处理结果生成 View 视图。
View(视图)
:最终产出结果,常用视图如 jsp、html。
SpringMVC 基础配置
常规配置
Controller 加载控制
SpringMVC 的处理器对应的 bean 必须按照规范格式开发,为了避免加入无效的 bean,可通过 bean 加载过滤器进行包含设定或排除设定。
例如,表现层 bean 标注通常设定为 @Controller,因此可以通过注解名称进行过滤控制:
<context:component-scan base-package="com">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
静态资源加载
<!--放行指定类型静态资源配置方式-->
<mvc:resources mapping="/img/**" location="/img/"/>
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/css/**" location="/css/"/>
<!--SpringMVC提供的通用资源放行方式-->
<mvc:default-servlet-handler/>
中文乱码处理
web.xml:
<!-- 乱码处理过滤器,与Servlet中使用的完全相同,差异之处在于处理器的类由Spring提供 -->
<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.xml 和 spring-mvc.xml 。
注意:
实现示例:
- 使用注解形式,将 SpringMVC 核心配置文件替换为配置类:
package com.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.Controller;
@Configuration
@ComponentScan(
value="com",
includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes={Controller.class})
)
public class SpringMvcConfig implements WebMvcConfigurer {
// 注解配置放行指定资源格式
// @Override
// public void addResourceHandlers(ResourceHandlerRegistry registry) {
// registry.addResourceHandler("/img/**").addResourceLocations("/img/");
// registry.addResourceHandler("/js/**").addResourceLocations("/js/");
// registry.addResourceHandler("/css/**").addResourceLocations("/css/");
// }
// 注解配置通用放行资源的格式
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();;
}
}
- 替换 web.xml:基于 servlet3.0 规范,自定义 Servlet 容器初始化配置类,加载 SpringMVC 核心配置类
package com.config;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.util.EnumSet;
import java.util.Objects;
public class ServletInitConfig extends AbstractDispatcherServletInitializer {
/*
创建 Servlet 容器时,使用注解的方式加载 SpringMVC 配置类中的信息,并加载成 Web 专用的 ApplicationContext 对象
该对象放入了 ServletContext 范围,后期在整个 Web 容器中可以随时获取调用
*/
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
// 注解配置映射地址方式,服务于 SpringMVC 的核心控制器 DispatcherServlet
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
protected WebApplicationContext createRootApplicationContext() {
return null;
}
// 乱码处理作为过滤器,在 servlet 容器启动时进行配置
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(Objects.<ServletContext>requireNonNull(servletContext));
CharacterEncodingFilter cef = new CharacterEncodingFilter();
cef.setEncoding("UTF-8");
FilterRegistration.Dynamic registration = servletContext.addFilter("characterEncodingFilter", cef);
registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD,
DispatcherType.INCLUDE), false, "/*");
}
}
请求
请求映射:@RequestMapping
@RequestMapping 使用:
- 类型:类注解;方法注解
- 位置:处理器类定义上方;处理器类中的方法定义上方
- 作用:为当前处理器中所有方法设定公共的访问路径前缀;绑定请求地址与对应处理方法间的关系
// 示例:方法注解
@Controller
public class UserController {
// 访问 URI:/user/requestURL1
@RequestMapping("/requestURL1")
public String requestURL2() {
return "page.jsp";
}
}
// 示例:类注解
@Controller
@RequestMapping("/user")
public class UserController {
// 访问 URI:/user/requestURL2
@RequestMapping("/requestURL2")
public String requestURL2() {
return "page.jsp";
}
}
常用属性:
@RequestMapping(
value="/requestURL3", // 设定请求路径,与path属性、value属性相同
method = RequestMethod.GET, // 设定请求方式
params = "name", // 设定请求参数条件
headers = "content-type=text/*", // 设定请求消息头条件
consumes = "text/*", // 用于指定可以接收的请求正文类型(MIME类型)
produces = "text/*" // 用于指定可以生成的响应正文类型(MIME类型)
)
public String requestURL3() {
return "/page.jsp";
}
普通类型传参
// URL 访问:http://localhost:8080/requestParam1?name=xiaoming&age=14
@RequestMapping("/requestParam1")
public String requestParam1(String name ,String age){
System.out.println("name="+name+", age="+age);
return "page.jsp";
}
@RequestParam
- 类型:形参注解
- 位置:处理器类中的方法形参前方
- 作用:绑定请求参数与处理方法形参间的关系
示例:
// http://localhost:8080/requestParam2?userName=Jock
@RequestMapping("/requestParam2")
public String requestParam2(@RequestParam(
name = "userName",
required = true,
defaultValue = "xiaohuang") String name) {
System.out.println("name="+name);
return "page.jsp";
}
- 当未传参即直接访问“/requestParam2”时,方法会取默认值“xiaohuang”。
- 当配置了“required=true”但未配置“defaultValue”时,访问时不传参则会报 400 错。
对象类型传参
POJO
当使用 POJO(简单 Java 对象)时,传参名称与 POJO 类属性名保持一致即可。
- POJO 类:
package com.bean;
public class User {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
- Controller:
// URL 访问:http://localhost:8080/requestParam3?name=xiaodong&age=18
@RequestMapping("/requestParam3")
public String requestParam3(User user){
System.out.println("name="+user.getName());
return "page.jsp";
}
参数冲突
当 POJO 的属性与其他形参出现同名问题时,将被同时赋值。
// 访问 URL:http://localhost:8080/requestParam4?name=xiaoyi&age=14
@RequestMapping("/requestParam4")
public String requestParam4(User user, String age){
System.out.println("user.age="+user.getAge()+", age="+age); // user.age=14, age=14
return "page.jsp";
}
建议使用 @RequestParam 注解进行区分。
复杂对象类型
当对象中出现对象属性时,则要求入参名称与对象层次结构名称保持一致。
对象集合
1)当复杂对象中出现用 List 保存对象数据时,要求入参名称与对象层次结构名称保持一致,并使用数组格式描述集合中对象的位置。
- bean:
public class User {
private String name;
private Integer age;
private List<Address> addresses;
}
public class Address {
private String province;
private String city;
private String address;
}
- Controller:
// 访问URL:http://localhost:8080/requestParam7?addresses[0].province=bj&addresses[1].province=tj
@RequestMapping("/requestParam7")
public String requestParam7(User user){
System.out.println("user.addresses="+user.getAddresses());
return "page.jsp";
}
注意:The valid characters are defined in RFC 7230 and RFC 3986
问题解决
2)当复杂对象中出现用 Map 保存对象数据时,要求入参名称与对象层次结构名称保持一致,并使用映射格式描述集合中对象的位置。
- bean:
public class User {
private String name;
private Integer age;
private Map<String, Address> addressMap;
}
public class Address {
private String province;
private String city;
private String address;
}
- controller:
// 访问 URL:http://localhost:8080/requestParam8?addressMap['home'].province=bj&addressMap['job'].province=tj
@RequestMapping("/requestParam8")
public String requestParam8(User user){
System.out.println("user.addressMap="+user.getAddressMap());
return "page.jsp";
}
数组集合类型传参
// 访问 URL:http://localhost:8080/requestParam9?nick=xiaoming1&nick=xiaoming2
@RequestMapping("/requestParam9")
public String requestParam9(String[] nick){
System.out.println(nick[0]+", "+nick[1]); // xiaoming1, xiaoming2
return "page.jsp";
}
// 访问 URL:http://localhost:8080/requestParam10?nick=xiaoming1&nick=xiaoming2
@RequestMapping("/requestParam10")
public String requestParam10(@RequestParam("nick") List<String> nick){
System.out.println(nick); // [xiaoming1, xiaoming2]
return "page.jsp";
}
注意:
-
SpringMVC 默认将 List 作为对象处理,赋值前先创建对象,然后将 nick 作为对象的属性进行处理。而由于 List 是接口,无法创建对象,报无法找到构造方法异常;修复类型为可创建对象的 ArrayList 类型后,对象可以创建,但没有 nick 属性,因此数据为空。
-
此时需要告知 SpringMVC 的处理器 nick 是一组数据,而不是一个单一数据。
-
因此通过 @RequestParam 注解,将数量大于 1 个的 names 参数打包成参数数组后, SpringMVC 才能识别该数据格式,并判定形参类型是否为数组或集合,并按数组或集合对象的形式操作数据。
类型转换器
SpringMVC 会对接收的参数进行自动类型转换,该工作通过 Converter 接口实现。
标量转换器:
- StringToBooleanConverter String —> Boolean
- ObjectToStringConverter Object —> String
- StringToNumberConverterFactory String —> Number( Integer、Long 等)
- NumberToNumberConverterFactory Number子类型之间(Integer、Long、Double 等)
- StringToCharacterConverter String —> java.lang.Character
- NumberToCharacterConverter Number子类型(Integer、Long、Double 等) —> java.lang.Character
- CharacterToNumberFactory java.lang.Character —> Number 子类型(Integer、Long、Double 等)
- StringToEnumConverterFactory String —> enum 类型
- EnumToStringConverter enum 类型 —> String
- StringToLocaleConverter String —> java.util.Local
- PropertiesToStringConverter java.util.Properties —> String
- StringToPropertiesConverter String —> java.util.Properties
集合、数组相关转换器:
- ArrayToCollectionConverter 数组 —> 集合(List、Set)
- CollectionToArrayConverter 集合(List、Set) —> 数组
- ArrayToArrayConverter(数组间转换)
- CollectionToCollectionConverter 集合间(List、Set)
- MapToMapConverter Map间
- ArrayToStringConverter 数组 —> String 类型
- StringToArrayConverter String —> 数组(实现方式为 trim 后使用 "," 进行 split)
- ArrayToObjectConverter 数组 —> Object
- ObjectToArrayConverter Object —> 单元素数组
- CollectionToStringConverter 集合(List、Set) —> String
- StringToCollectionConverter String —> 集合(List、Set)(实现方式为 trim 后使用 "," 进行 split)
- CollectionToObjectConverter 集合 —> Object
- ObjectToCollectionConverter Object —> 单元素集合
默认转换器:
- ObjectToObjectConverter(Object 间转换)
- IdToEntityConverter Id —> Entity
- FallbackObjectToStringConverter Object —> String
日期类型格式转换
配置版:声明自定义的转换格式并覆盖系统转换格式
<!-- 启用自定义Converter -->
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- 1.设定格式类型Converter,注册为Bean,受SpringMVC管理 -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- 2.自定义Converter格式类型设定,该设定使用的是同类型覆盖的思想 -->
<property name="formatters">
<!-- 3.使用set保障相同类型的转换器仅保留一个,避免冲突 -->
<set>
<!-- 4.设置具体的格式类型 -->
<bean class="org.springframework.format.datetime.DateFormatter">
<!-- 5.类型规则 -->
<property name="pattern" value="yyyy-MM-dd"/>
</bean>
</set>
</property>
</bean>
注解版:
- 名称:@DateTimeFormat
- 类型:形参注解、成员变量注解
- 位置:形参前面或成员变量上方
- 作用:为当前参数或变量指定类型转换规则
- 注意:依赖注解驱动支持(<mvc:annotation-driven />)
- 范例:
// 形参前
// 访问 URL:http://localhost:8080/requestParam11?date=2021-12-12
@RequestMapping("/requestParam11")
public String requestParam11(@DateTimeFormat(pattern="yyyy-MM-dd") Date date){
System.out.println("date="+date);
return "page.jsp";
}
// 成员变量上方
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birthday;
自定义类型转换器
1)实现 Converter 接口,并制定转换前与转换后的类型:
- 配置:
<!-- 1.将自定义Converter注册为Bean,受SpringMVC管理 -->
<bean id="myDateConverter" class="com.itheima.converter.MyDateConverter"/>
<!-- 2.设定自定义Converter服务bean -->
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<!-- 3.注入所有的自定义Converter,该设定使用的是同类型覆盖的思想 -->
<property name="converters">
<!-- 4.set保障同类型转换器仅保留一个,去重规则以Converter<S,T>的泛型为准 -->
<set>
<!-- 5.具体的类型转换器 -->
<ref bean="myDateConverter"/>
</set>
</property>
</bean>
- 实现类:
// 自定义类型转换器,实现Converter接口,接口中指定的泛型即为最终作用的条件
// 本例中的泛型填写的是<String,Date>,最终出现字符串转日期时,该类型转换器生效
public class MyDateConverter implements Converter<String, Date> {
// 重写接口的抽象方法,参数由泛型决定
public Date convert(String source) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
// 类型转换器无法预计使用过程中出现的异常,因此必须在类型转换器内部捕获,不允许抛出,框架无法预计此类异常如何处理
try {
date = df.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
2)通过注册自定义转换器,将该功能加入到 SpringMVC 的转换服务 ConverterService 中:
<!-- 开启注解驱动,加载自定义格式化转换器对应的类型转换服务 -->
<mvc:annotation-driven conversion-service="conversionService"/>
响应
页面跳转:转发与重定向
// 转发
@RequestMapping("/showPage1")
public String showPage1() {
System.out.println("user mvc controller is running ...");
return "forward:page.jsp"; // 支持访问WEB-INF下的页面
}
// 重定向
@RequestMapping("/showPage2")
public String showPage2() {
System.out.println("user mvc controller is running ...");
return "redirect:page.jsp"; // 不支持访问WEB-INF下的页面
}
请求转发与重定向的区别:
-
当使用请求转发时,Servlet 容器将使用一个内部的方法来调用目标页面,新的页面继续处理同一个请求,而浏览器将不会知道这个过程(即服务器行为)。与之相反,重定向的含义是第一个页面通知浏览器发送一个新的页面请求。因为当使用重定向时,浏览器中所显示的 URL 会变成新页面的 URL(浏览器行为)。而当使用转发时,该 URL 会保持不变。
-
重定向的速度比转发慢,因为浏览器还得发出一个新的请求。
-
同时,由于重定向产生了一个新的请求,所以经过一次重定向后,第一次请求内的对象将无法使用。
总结:
- 重定向:两次请求,浏览器行为,地址栏改变,请求域中的数据会丢失。
- 请求转发:一次请求,服务器行为,地址栏不变,请求域中的数据不丢失。
怎么选择是重定向还是转发呢?
-
通常情况下转发更快,而且能保持请求内的对象,所以它是第一选择。但是由于在转发之后,浏览器中 URL 仍然指向开始页面,此时如果重载当前页面,开始页面将会被重新调用。如果不想看到这样的情况,则选择重定向。
-
不要仅仅为了把变量传到下一个页面而使用 session 作用域,那会无故增大变量的作用域,转发也许可以帮助解决这个问题。
- 重定向:以前的请求中存放的变量全部失效,并进入一个新的请求作用域。
- 转发:以前的请求中存放的变量不会失效,就像把两个页面拼到了一起。
页面访问快捷设定(InternalResourceViewResolver)
通常,展示页面的保存位置比较固定且结构相似,因此可以设定通用的访问路径,来简化页面配置。
示例:
<!-- 设定页面加载的前缀后缀,仅适用于默认形式,不适用于手工标注转发或重定向的方式 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
public String showPage3() {
return "page";
}
而如果未设定返回值,使用 void 类型,则默认使用访问路径来拼接前后缀:
// 最简页面配置方式:使用访问路径作为返回的页面名称,省略返回值
@RequestMapping("/showPage5")
public void showPage5() {
System.out.println("user mvc controller is running ...");
}
带数据页面跳转
- 实体类:
public class Book {
private String name;
private Double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
- 控制层:
import com.bean.Book;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
@Controller
public class BookController {
// 使用原生response对象响应数据
@RequestMapping("/showData1")
public void showData1(HttpServletResponse response) throws IOException {
response.getWriter().write("message");
}
// 使用原生request对象传递参数
@RequestMapping("/showPageAndData1")
public String showPageAndData1(HttpServletRequest request) {
request.setAttribute("name", "xiaoming");
return "page";
}
// 使用Model形参传递参数
@RequestMapping("/showPageAndData2")
public String showPageAndData2(Model model) {
Book book = new Book();
book.setName("SpringMVC入门案例");
book.setPrice(66.66d);
// 添加数据的方式
model.addAttribute("name", "xiaoming");
model.addAttribute("book", book);
return "page";
}
// 使用ModelAndView形参传递参数,该对象还封装了页面信息
@RequestMapping("/showPageAndData3")
public ModelAndView showPageAndData3(ModelAndView modelAndView) {
// ModelAndView mav = new ModelAndView(); // 替换形参中的参数
Book book = new Book();
book.setName("SpringMVC入门案例");
book.setPrice(66.66d);
// 添加数据的方式
modelAndView.addObject("book", book);
modelAndView.addObject("name", "xiaoming");
// 设置返回页面(若该方法存在多个,则以最后一个为准)
modelAndView.setViewName("page");
// 返回值设定成ModelAndView对象
return modelAndView;
}
// ModelAndView对象支持转发的手工设定,该设定不会启用前缀后缀的页面拼接格式
@RequestMapping("/showPageAndData4")
public ModelAndView showPageAndData4(ModelAndView modelAndView) {
modelAndView.setViewName("forward:/WEB-INF/pages/page.jsp");
return modelAndView;
}
// ModelAndView对象支持重定向的手工设定,该设定不会启用前缀后缀的页面拼接格式
@RequestMapping("/showPageAndData5")
public ModelAndView showPageAndData6(ModelAndView modelAndView) {
modelAndView.setViewName("redirect:index.jsp");
return modelAndView;
}
}
返回 JSON 数据
- 导入 maven 坐标:
<!--json相关坐标3个-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
- Controller:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
// 使用@ResponseBody将返回的结果作为响应内容,而非响应的页面名称
@RequestMapping("/showData2")
@ResponseBody
public String showData2(){
return "{\"name\":\"xiaoming\"}";
}
// 使用jackson进行json数据格式转化(会有中文乱码问题)
@RequestMapping("/showData3")
@ResponseBody
public String showData3() throws JsonProcessingException {
Book book = new Book();
book.setName("SpringMVC入门案例");
book.setPrice(66.66d);
ObjectMapper om = new ObjectMapper();
return om.writeValueAsString(book);
}
/*
<!--开启springmvc注解驱动,对@ResponseBody的注解进行格式增强,追加其类型转换的功能,具体实现由MappingJackson2HttpMessageConverter进行-->
<mvc:annotation-driven/>
*/
// 使用SpringMVC注解驱动,对标注@ResponseBody注解的控制器方法进行结果转换
// 由于返回值为引用类型,自动调用jackson提供的类型转换器进行格式转换
@RequestMapping("/showData4")
@ResponseBody
public Book showData4() {
Book book = new Book();
book.setName("SpringMVC入门案例");
book.setPrice(66.66d);
return book;
}
// 转换集合类型数据
@RequestMapping("/showData5")
@ResponseBody
public List showData5() {
Book book1 = new Book();
book1.setName("SpringMVC入门案例");
book1.setPrice(66.66d);
Book book2 = new Book();
book2.setName("SpringMVC入门案例");
book2.setPrice(66.66d);
ArrayList<Book> al = new ArrayList<>();
al.add(book1);
al.add(book2);
return al; // 返回 [{"name":"SpringMVC入门案例","price":66.66},{"name":"SpringMVC入门案例","price":66.66}]
}
Servlet 相关接口
SpringMVC 提供访问原始 Servlet 接口 API 的功能,通过形参声明即可。
@RequestMapping("/servletApi")
public String servletApi(HttpServletRequest request,
HttpServletResponse response, HttpSession session){
System.out.println(request); // org.apache.catalina.connector.RequestFacade@6d3a1615
System.out.println(response); // org.apache.catalina.connector.ResponseFacade@55405578
System.out.println(session); // org.apache.catalina.session.StandardSessionFacade@714a7020
request.setAttribute("name", "xiaoming");
System.out.println(request.getAttribute("name")); // xiaoming
return "page.jsp";
}
Header 数据获取:
- 名称:@RequestHeader
- 类型:形参注解
- 位置:处理器类中的方法形参前方
- 作用:绑定请求头数据与对应处理方法形参间的关系
// header 数据获取
@RequestMapping("/headApi")
public String headApi(@RequestHeader("Accept-Language") String head){
System.out.println(head); // zh-CN,zh;q=0.9
return "page.jsp";
}
Cookie 数据获取:
- 名称:@CookieValue
- 类型:形参注解
- 位置:处理器类中的方法形参前方
- 作用:绑定请求 Cookie 数据与对应处理方法形参间的关系
// cookie 数据获取
@RequestMapping("/cookieApi")
public String cookieApi(@CookieValue("JSESSIONID") String jsessionid){
System.out.println(jsessionid);
return "page.jsp";
}
Session 数据获取:
- 名称:@SessionAttribute
- 类型:形参注解
- 位置:处理器类中的方法形参前方
- 作用:绑定请求 Session 数据与对应处理方法形参间的关系
// 测试用方法,为下面的试验服务,用于在session中放入数据
@RequestMapping("/setSessionData")
public String setSessionData(HttpSession session){
session.setAttribute("name", "xiaoming");
return "page";
}
// session 数据获取
@RequestMapping("/sessionApi")
public String sessionApi(@SessionAttribute("name") String name){
System.out.println(name); // 获取session中的name值
return "page.jsp";
}
Session 数据设置:
- 名称:@SessionAttributes
- 类型:类注解
- 位置:处理器类上方
- 作用:声明放入 session 范围的变量名称,适用于 Model 类型数据传参
@Controller
// 设定当前类中名称为age和gender的变量放入session范围(不常用,了解即可)
@SessionAttributes(names={"age","gender"})
public class ServletController {
// 配合 @SessionAttributes(names={"age","gender"}) 使用
// 将数据放入session存储范围,通过Model对象实现数据set,通过@SessionAttributes注解实现范围设定
@RequestMapping("/setSessionData2")
public String setSessionDate2(Model model) {
model.addAttribute("age",39);
model.addAttribute("gender","男");
return "page.jsp";
}
}