SpringMVC 概述

SSM 简介

SSM 三层架构

  • 表现层:负责数据展示

  • 业务层:负责业务处理

  • 数据层:负责数据操作

MVC 简介

MVC(Model View Controller)是一种用于设计及创建 Web 应用程序表现层的模式。

  • Model(模型):数据模型,用于封装数据

  • View(视图):页面视图,用于展示数据

    • jsp
    • html
  • Controller(控制器):处理用户交互的调度器,用于根据用户需求处理程序逻辑

    • Servlet
    • SpringMVC

SpringMVC 简介

SpringMVC 是一种基于 Java 实现的、MVC 模型的、轻量级的 Web 框架。

SpringMVC 优点

  1. 使用简单
  2. 性能突出(相比现有的框架技术)
  3. 灵活性强

入门案例

SpringMVC 工作流程分析:

  1. 服务器启动:

    1. 加载 web.xml 中 DispatcherServlet;
    2. 读取 spring-mvc.xml 中的配置,加载所有 com 包中所有标记为 bean 的类;
    3. 读取 bean 中方法上方标注 @RequestMapping 的内容;
  2. 处理请求:
    1. DispatcherServlet 配置拦截所有请求“/”;
    2. 使用请求路径与所有加载的 @RequestMapping 的内容进行比对;
    3. 执行对应的方法;
    4. 根据方法的返回值在 webapp 目录中查找对应的页面并展示。

实现示例

  1. 导入 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>
  1. 定义表现层处理器 Controller(等同于 Servlet),并配置成 Spring 的 bean:
@Controller
public class UserController { public void save(){
System.out.println("user mvc controller is running ...");
}
}
  1. 定义 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>
  1. 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>
  1. 设定具体 Controller 的访问路径与返回页面(等同于 Servlet 在 web.xml 中的配置):
// 设定当前方法的访问映射地址
@RequestMapping("/save")
// 设置当前方法返回值类型为String,用于指定请求完成后跳转的页面
public String save(){
System.out.println("user mvc controller is running ...");
// 设定具体跳转的页面
return "success.jsp";
}

Spring 技术架构

  1. DispatcherServlet(前端控制器):是整体流程控制的中心,由其调用其它组件处理用户的请求,有效降低了组件间的耦合性。
  2. HandlerMapping(处理器映射器):负责根据用户请求找到对应具体的 Handler 处理器。
  3. Handler(处理器):业务处理的核心类,通常由开发者编写,描述具体的业务。
  4. HandlAdapter(处理器适配器):通过它对处理器进行执行。
  5. View Resolver(视图解析器):将处理结果生成 View 视图。
  6. 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 。

注意

实现示例

  1. 使用注解形式,将 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();;
}
}
  1. 替换 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";
}
}

SpringMVC 入门、请求、响应的更多相关文章

  1. <SpringMvc>入门四 响应结果

    1.响应String类型 根据试图解析器,去找相对应的jsp Model将对象存在request中 2.响应void类型 可以看出,此时void方法执行了,系统默认会去找testVoid.jsp 意思 ...

  2. ajax和springmvc的请求响应原理——深入理解jQuery中$.get、$.post、$.getJSON和$.ajax的用法

    1,四大重要部分: 请求链接 post请求和get请求 请求参数形式 响应内容形式 2,从springmvc的controller角度,controller能接收到请求的前提 请求链接必须对应 pos ...

  3. SpringMVC之请求响应(上)

    1.OutPutController package com.tz.controller; import java.util.Map; import org.springframework.stere ...

  4. SpringMVC入门和常用注解

    SpringMVC的基本概念 关于 三层架构和 和 MVC 三层架构 我们的开发架构一般都是基于两种形式,一种是 C/S 架构,也就是客户端/服务器,另一种是 B/S 架构,也就 是浏览器服务器.在 ...

  5. springMvc REST 请求和响应

    前言: 突然怎么也想不起来  springMvc REST 请求的返回  类型了!   (尴尬+究竟)  然后本着 方便的想法 百度了一下 发现了个问题,大家在写      springMvc RES ...

  6. Spring系列 SpringMVC的请求与数据响应

    Spring系列 SpringMVC的请求与数据响应 SpringMVC的数据响应 数据响应的方式 y以下案例均部署在Tomcat上,使用浏览器来访问一个简单的success.jsp页面来实现 Suc ...

  7. JSP请求响应流程入门介绍

    一个完整的jsp请求响应流程可以简单的使用下图表示: 过滤器:直观的了解,就是对请求做一个过滤作用,比如身份验证,验证不通过的不让他继续往下走 Servlet:请求处理中心,这个也是我们写业务逻辑的地 ...

  8. 【Spring】SpringMVC入门示例讲解

    目录结构: // contents structure [-] SpringMVC是什么 Spring MVC的设计原理 SpringMVC入门示例 1,复制Jar包 2,Web.xml文件 3,My ...

  9. SpringMVC入门第二天

    SpringMVC第二天 1.   回顾 1.Springmvc介绍? Springmvc是Spring公司 2.Springmvc入门程序 第一步:Web工程 第二步:导Jar包 第三步:web.x ...

随机推荐

  1. [cf516E]Drazil and His Happy Friends

    令$d=\gcd(n,m)$,存在$x$和$y$使得$xn+i=ym+j$的充要条件是$i\equiv j(mod \ d)$,因此将$xd+i$(其中$0\le i<d$)作为一组,共有$d$ ...

  2. 【GitHub】本地代码上传

    本地代码上传GitHub 2019-11-18  20:03:45  by冲冲 1.注册GitHub https://github.com/ 2.安装Git工具 https://git-for-win ...

  3. page_fault_in_nonpaged_area异常解决方案(已解决)

    电脑在运行虚拟机的时候异常重启,多次打开结果一样,问了客服告诉我导致蓝屏的原因很多,可能是驱动不兼容,系统,或其他.{没点有用的} 百度到这个方案: 打开->此电脑->右键属性->高 ...

  4. 面试官:Java 线程如何启动的?

    摘要:Java 的线程创建和启动非常简单,但如果问一个线程是怎么启动起来的往往并不清楚,甚至不知道为什么启动时是调用start(),而不是调用run()方法呢? 本文分享自华为云社区<Threa ...

  5. 【豆科基因组】利马豆/洋扁豆Lima bean(Phaseolus lunatus L.)基因组2021NC

    目录 一.来源 二.结果 扁豆的染色体水平高质量组装 扁豆相关农艺性状的QTL定位 直系/旁系同源的演化和物种形成事件 与农艺性状相关基因的直系同源物 群体结构分析揭示扁豆遗传簇 豆荚发育过程中的基因 ...

  6. alpine切换源 安装慢 apk add很慢

    alpine切换源 安装慢 apk add很慢 阿里镜像 sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/reposit ...

  7. logname

    logname命令用来显示用户名称. 语法 logname(选项) 选项 --help:在线帮助: --vesion:显示版本信息.

  8. shell编程100列

    1.编写hello world脚本 #!/bin/bash# 编写hello world脚本 echo "Hello World!"2.通过位置变量创建 Linux 系统账户及密码 ...

  9. windows下typora图片自动上传到图床(附带腾讯云教程)

    目录 1. 背景 2. 在Typora中使用 3. 安装 3.1 安装教程环境说明 3.2 安装步骤 3.3 配置图床 3.3.1 插件配置 3.3.2 腾讯云参数获取 3.3.2.1 新建子用户,获 ...

  10. android Fragment跳转Fragment

    android Fragment跳转Fragment,最新的android studio3 在系统模板建立的BottomNavigationView 中跳转方式 此版本下不能用FragmentMana ...