SpringMVC
1、简单概述
springmvc是用来做web的简化,web开发的底层是servlet,所以springmvc是在servlet的基础之上做了增强;
传统的web开发模式下,无非离不开servlet和fileter,以及对静态资源的访问。
其中利用filter来进行路径匹配拦截;利用servlet中的request和response来做为响应。
在前后端分离之后,还需要利用token来校验当前的用户的权限等等操作,这一块通常都是在filter中来进行实现的。
在以前的对web阶段的封装过程中,都是自己来对其进行实现的,功能不是很强大,现在可以使用springmvc中提供的一些组件来进行操作,这一块很有意思,可以多来学习学习使用。
springmvc又是spring,spring抽象的理解成是一种容器,是用来装对象的。springmvc也是用来容纳对象的,容纳的对象是控制器对象
我们平时使用的是@Controller来创建控制器对象,把对象放在控制器对象中去,把对象放入到容器中去。
把创建出来的对象当做是控制器来进行使用,通过控制器对象可以用来接收用户的请求,显示处理的结果,
就把其当成是servlet来进行使用。
控制器对象不是servlet,而是普通类的对象。是springmvc赋予的具有特殊意义的对象,通过@Controller来进行创建的。
它通过一套注解,让一个简单的java类成为处理请求的控制器,而无须实现任何接口(跟Servlet对比)
清晰的角色划分:
- 前端控制器(dispatcherServlet)
- 请求到处理器映射(HandlerMapping)
- 处理器适配器(HandlerAdapter) 通过HandlerAdapter可以支持任意的类作为处理器,servlet就不是这样子来进行操作了,servlet需要通过继承servlet接口的形式才能够进行处理
- 视图解析器(ViewResolver)
- 处理器或页面控制器(Controller)
- 验证器( Validator)
- 命令对象(Command 请求参数绑定到的对象就叫命令对象)
- 表单对象(Form Object 提供给表单展示的对象就叫表单对象)。
2、简介
1. 三层架构和MVC
三层架构回顾
MVC模式
- 体现在web层:
- M:Model,模型层
- V:View,视图层
- C:Controller,控制层
2. SpringMVC简介
1. 什么是SpringMVC
- SpringMVC是一种基于Java的、实现MVC设计模型的、请求驱动类型的(基于HTTP协议)、轻量级Web框架,属于 Spring FrameWork 的后续产品。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。
- SpringMVC已经成为目前最主流的 MVC 框架之一,并且随着Spring3.0的发布,全面超越 Struts2,成为最优秀的 MVC 框架。
- 它通过一套注解,让一个简单的java类成为处理请求的控制器,而无须实现任何接口(跟Servlet对比)。同时它还支持RESTful编程风格的请求。
2. SpringMVC的优势
-
清晰的角色划分:
-
分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要。
-
由于命令对象就是一个POJO,无需继承框架特定API,可以使用命令对象直接作为业务对象。
-
和Spring 其他框架无缝集成,是其它Web框架所不具备的。
-
可适配,通过HandlerAdapter可以支持任意的类作为处理器。
-
可定制性,HandlerMapping、ViewResolver等能够非常简单的定制。
-
功能强大的数据验证、格式化、绑定机制。
-
利用Spring提供的Mock对象能够非常简单的进行Web层单元测试。
-
强大的JSP标签库,使JSP编写更容易。
3. SpringMVC和Struts的对比【了解】
-
共同点:
- 它们都是表现层(web层)框架,都是基于MVC模型编写的。
- 它们的底层都离不开原始ServletAPI。
- 它们处理请求的机制都是一个核心控制器。
-
区别:
-
Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
-
Spring MVC 是基于方法设计的,而Struts2是基于类,Struts2每次执行都会创建一个动作类。所以Spring MVC 会稍微比 Struts2 快些。
-
Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便
JSR303 是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面,就可以在需要校验的时候进行校验了。)
-
Struts2 的OGNL 表达式使页面的开发效率相比Spring MVC 更高些,但执行效率并没有比JSTL提升,尤其是struts2的表单标签,远没有html执行效率高。
-
3、快速入门【重点】
需求描述
需求分析
- 准备工作
- 创建web项目,导入依赖
- 创建页面:
success.jsp
- 编写控制器:
Demo01QuickStartController
(类似于Servlet,和客户端进行交互)
- 提供SpringMVC配置
- 部署测试
需求实现
1. 准备工作
1.1 创建web项目,导入依赖
<dependencies>
<!--springmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--servlet-api-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<!--jsp-api-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
1.2 创建页面:
- 直接在webapp里创建的
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>成功</title>
</head>
<body>
<h1>成功页面</h1>
</body>
</html>
2. 编写控制器
- 在
com.guang.controller
包中创建类Demo01QuickStartController
- 类上增加
@Controller
注解,声明成为一个bean - 创建
quickstart
方法,并在方法上增加@RequestMapping
注解,声明方法的访问路径
@Controller
public class Demo01QuickStartController {
@RequestMapping("/quickstart")
public String quickstart(){
System.out.println("quickstart......");
//跳转到success.jsp页面
return "/success.jsp";
}
}
3. 提供SpringMVC配置
3.1 编写配置文件springmvc.xml
- 在
resources
中创建springmvc的配置文件springmvc.xml
- 要开启组件扫描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--开启组件扫描-->
<context:component-scan base-package="com.guang.controller"/>
</beans>
3.2 修改配置文件web.xml
- 在
webapp/WEB-INF/web.xml
中配置前端控制器dispatcherServlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--配置SpringMVC的前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.dispatcherServlet</servlet-class>
<!-- 指定springmvc配置文件的位置 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- 设置dispatcherServlet控制器,当服务器一启动时就创建对象 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
4. 部署测试
- 把项目部署到tomcat中,设置项目路径为
/mvc01
,启动tomcat - 使用浏览器访问:
http://localhost:8080/mvc01/quickstart
quickstart
方法被访问到,并且页面跳转到了success.jsp
步骤小结
- 创建web工程,导入依赖:
spring-webmvc, servlet-api, jsp-api
- 编写Controller
- 提供springmvc.xml:开启组件扫描
- 修改web.xml:配置前端控制器dispatcherServlet
三、配置详解
1. 原理分析
请求和响应的过程
SpringMVC的详细执行流程
SpringMVC的三大组件
HandlerMapping
处理器映射器- 作用:根据客户端请求的资源路径,查找匹配的
Controller
及拦截器链
- 作用:根据客户端请求的资源路径,查找匹配的
HandlerAdapter
处理器适配器- 作用:用于适配调用不同的
Controller
,得到模型和视图
- 作用:用于适配调用不同的
ViewResolver
视图解析器- 作用:用于解析视图,根据视图路径找到真实视图(页面)
SpringMVC的详细执行流程
- 客户端发请求到
dispatcherServlet
dispatcherServlet
dispatcherServlet
- 通过
HandlerAdapter
处理器适配器,调用控制器Controller
- 得到
ModelAndView
对象(其中View指视图路径,Model要响应的数据对象)
- 通过
dispatcherServlet
- 通过
ViewResolver
解析视图,得到真实视图(视图路径对应的页面) - 渲染视图(把Model里的数据填充到View里)
- 通过
- 把最终渲染的结果,响应到客户端
需要我们做的事情有:
小结
- 客户端发请求到dispatcherServlet
- dispatcherServlet查找Handler(Controller里的方法)
- dispatcherServlet要调用Handler
- dispatcherServlet要解析视图
- dispatcherServlet要渲染视图:数据的填充
- dispatcherServlet返回响应:把渲染的结果响应给客户端
2. springmvc.xml
配置详解
基本配置示例
<!--开启组件扫描-->
<context:component-scan base-package="com.guang.controller"/>
<!--开启mvc的注解驱动-->
<mvc:annotation-driven/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 静态资源的配置:让SpringMVC不处理静态资源 -->
<mvc:default-servlet-Handler/>
mvc的注解驱动
配置语法
<mvc:annotation-driven/>
配置说明
- 在SpringMVC中,处理器映射器,处理器适配器,视图解析器 被称为三大组件
- 在springmvc.xml中配置
<mvc:annotation-driven/>
标签,可以加载SpringMVC的组件
视图解析器配置
1) 视图路径的配置方式
- SpringMVC把显示层的内容称为视图,例如JSP页面就是视图。在
Controller
的方法中,返回的字符串就是跳转的视图路径 - 视图的路径有两种写法:
- 物理视图:
/success.jsp
,即:视图的真实路径(完整路径)- 直观,但是写起来麻烦
- 逻辑视图:
success
,需要配合视图解析器,才能得到真实路径- 不直观,但是写起来简单
- 物理视图:
2) 物理视图的配置方式
- 在
Controller
的方法中,直接返回物理视图路径。 - 不需要配置视图解析器
@RequestMapping("/quickstart")
public String quickstart(){
System.out.println("quickstart......");
return "/success.jsp";
}
3) 逻辑视图的配置方式
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
@Controller
public class Demo01QuickStartController {
@RequestMapping("/quickstart")
public String quickstart(){
System.out.println("quickstart......");
return "success";
}
}
- 由视图解析器,帮我们把
prefix + "success" + suffix
,拼接成物理视图/success.jsp
处理静态资源
请求静态资源的说明
-
使用SpringMVC时,客户端访问静态资源时,会访问不到
-
Tomcat本身具备处理静态资源的能力,但是我们配置的
dispatcherServlet
把Tomcat的默认处理器覆盖掉了;而dispatcherServlet
没有处理静态资源的能力,所以:访问不到静态资源
两种配置方式解决问题
方案一:指定静态资源的位置
- 针对客户端对静态资源的请求,指定资源所在的位置。让SpringMVC直接去指定目录下加载
- 示例:
<!--
mapping:客户端请求的路径
location:资源所在的位置
-->
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/img/**" location="/img/"/>
<mvc:resources mapping="/css/**" location="/css/"/>
方案二:由Tomcat处理静态资源(推荐)
- 如果客户端请求了静态资源,dispatcherServlet处理不了,就交给Tomcat的原生Servlet来处理
- 示例:
<mvc:default-servlet-handler/>
小结
-
配置视图解析器
- Controller里的方法返回值要写逻辑视图
- 再配置视图解析器
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/pages/"/> <property name="suffix" value=".jsp"/> </bean>
-
如果有静态资源要访问,把静态资源仍然交给Tomcat处理
<mvc:default-servlet-handler/>
-
<mvc:annotation-driven/>
-
开启组件扫描
<context:component-scan base-pcakge="com.guang.controller"/>
3. web.xml
的配置
配置示例
<!--配置SpringMVC的前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.dispatcherServlet</servlet-class>
<!--配置springmvc.xml路径-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--服务器启动时,就创建dispatcherServlet对象-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!--把前端控制器设置为 默认的处理器(覆盖Tomcat的默认处理器)-->
<url-pattern>/</url-pattern>
</servlet-mapping>
配置说明
load-on-startup
:配置Servlet的创建时机,值是整数init-param
:配置Servlet的初始化参数url-pattern
:配置Servlet的路径,通常配置为/
拓展:dispatcherServlet
配置成/
和/*
的区别:
- 对JSP的处理不同。当客户端请求了
xxx.jsp
时 - 如果
dispatcherServlet
配置的是/*
,不能正常访问JSP - 如果
dispatcherServlet
配置的是/
,可以正常访问JSP/
是缺省匹配,优先级低于扩展名匹配(Tomcat里有JspServlet
,路径是*.jsp
)- 必定是由Tomcat来处理JSP,Tomcat本身具备查找和处理JSP的能力,可以正常访问JSP
知识回顾:Servlet的
urlPatterns
配置
配置语法:
完全匹配的路径:例如
/demo
,客户端必须请求/demo
才可以访问到这个Servlet目录匹配的路径:以
/
开头,/*
结尾:例如:
/*
:客户端的一切请求都会交给Servlet来处理/admin/*
:客户端请求/admin/任意
会访问到这个Servlet扩展名匹配的路径:以
*
开头,以扩展名结尾。例如:
*.jsp
:客户端请求任意.jsp
会访问到这个Servlet- Tomcat提供了处理jsp的Servlet:
org.apache.jasper.servlet.JspServlet
缺省匹配的路径:
/
。
- 客户端请求的路径,没有任何Servlet可以匹配到,就会由缺省匹配来处理
- Tomcat提供了缺省Servlet:
org.apache.catalina.servlets.DefaultServlet
- 缺省Servlet提供了处理静态资源的能力
以上四种配置语法,匹配的优先级是:
- 完全匹配 > 目录匹配 > 扩展名匹配 > 缺省匹配。
- 如果有多个Servlet的路径属于同一类,并且都能处理同一请求,那么匹配度更高的生效
4. Controller
的配置
配置示例
@Controller//必须声明成bean对象
@RequestMapping("/demo02")
public class Demo02MappingController {
@RequestMapping("/demo")
public String demo(){
System.out.println("demo......");
return "success";
}
}
@RequestMapping
注解
- 作用:通常用在
Controller
里,用于设置访问路径
注解语法
@RequestMapping(
value="访问路径",
method=请求方式,
params="请求参数"
)
- 常用属性:
- 如果注解用在Controller类上
使用示例
@Controller
@RequestMapping("/demo02")
public class Demo02MappingController {
// /demo02/mapping 能访问到
@RequestMapping("/mapping")
public String mapping(){
System.out.println("mapping");
return "success";
}
// /demo02/method,必须是POST方式才能访问到
@RequestMapping(value = "/method", method = RequestMethod.POST)
public String method(){
System.out.println("method");
return "success";
}
// /demo02/params,必须带有名称为username的表单参数,才能访问到
@RequestMapping(value = "/params", params = {"username"})
public String params(){
System.out.println("params");
return "success";
}
}
小结
四、获取请求数据
1. 接收表单参数【重点】
@RequestParam
绑定参数
- 介绍:把指定请求参数赋值给方法中的指定形参
- 语法:
@RequestParam(value="表单参数名称", required=是否必须)
- 属性:
- 作用位置:用在方法参数上,表示把指定名称表单参数值,赋值给方法参数
使用示例
<a href="${pageContext.request.contextpath}/param/requestParam?name=jack">@RequestParam</a><br>
@Controller
@RequestMapping("/other")
public class Demo02OtherController {
@RequestMapping("/requestParam")
public String requestParam(@RequestParam(value = "name", required = false, defaultValue = "aaa") String username){
System.out.println(username);
return "success";
}
}
简单参数绑定
要求:
示例:
<a href="${pageContext.request.contextpath}/param/simple?name=tom&age=20">简单参数</a>
<br/>
@Controller
@RequestMapping("/param")
public class Demo01ParamController {
@RequestMapping("/simple")
public String simpleParam(String name, Integer age){
System.out.println(name + ", " + age);
return "success";
}
}
日期参数类型转换
要求:
配置日期类型转换器
<mvc:annotation-driver conversion-service="conversionService"/>
<bean id="conversionService"
class="org.springframework.context.support.ConversionServicefactorybean">
<property name="converters">
<set>
<bean class="自定义类型转换器的全限定类名"/>
</set>
</property>
</bean>
示例:
- 自定义类型转换器
DateConverter
public class DateConverter implements Converter<String, Date> {
private SimpleDateFormat format = new SimpleDateFormat();
@Override
public Date convert(String source) {
if (source == null) {
throw new RuntimeException("日期为空,不能转换");
}
try {
//尝试以yyyy-MM-dd格式解析。
format.applyPattern("yyyy-MM-dd");
//解析成功,直接返回结果
return format.parse(source);
} catch (ParseException ignored) {}
try {
//尝试以yyyy/MM/dd格式解析。
format.applyPattern("yyyy/MM/dd");
//解析成功,直接返回结果
return format.parse(source);
} catch (ParseException e) {
//其它格式不支持
throw new RuntimeException("不支持的日期格式");
}
}
}
- 在
springmvc.xml
里注册类型转换器
<!--开启mvc注解驱动-->
<mvc:annotation-driven conversion-service="conversionService"/>
<!--配置转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServicefactorybean">
<property name="converters">
<set>
<bean class="com.guang.converter.DateConverter"/>
</set>
</property>
</bean>
<a href="${pageContext.request.contextpath}/param/date?name=tom&birthday=2000/02/02">日期参数:yyyy/MM/dd格式</a><br>
<a href="${pageContext.request.contextpath}/param/date?name=tom&birthday=2000-02-02">日期参数:yyyy-MM-dd格式</a><br>
@RequestMapping("/date")
public String dateParam(String name, Date birthday) {
System.out.println(name + ", " + birthday);
return "success";
}
类型转换器的步骤小结
-
创建一个类型转换器:
-
注册类型转换器
- 修改springmvc.xml
<mvc:annotation-driven conversion-service=""/> <bean id="conversionService" class="ConversionServicefactorybean的全限定类名"> <property name="converters"> <set> <bean class="我们写的类型转换器的全限定类名"/> </set> </property> </bean>
要求
示例
- 创建JavaBean:
User
- 注意:JavaBean中有日期类型,所以需要注册了日期类型转换器
public class User {
private String name;
private Integer age;
private Date birthday;
//get/set...
//toString...
}
- jsp
<a href="${pageContext.request.contextpath}/param/pojo?name=jack&age=20&birthday=2020/01/01">POJO参数</a>
@RequestMapping("/pojo")
public String pojoParam(User user){
System.out.println(user);
return "success";
}
绑定复杂POJO
要求
示例
- 创建JavaBean:
QueryVO
public class QueryVO {
private User user;
private List<User> userList;
private Map<String, User> userMap;
//get/set...
//toString...
}
<form action="${pageContext.request.contextpath}/param/complexPojo" method="post">
<h5>vo里的user</h5>
<input type="text" name="user.name" value="tom"><br>
<input type="text" name="user.age" value="20"><br>
<h5>vo里的userList</h5>
<input type="text" name="userList[0].name" value="tom1"><br>
<input type="text" name="userList[0].age" value="21"><br>
<input type="text" name="userList[1].name" value="tom2"><br>
<input type="text" name="userList[1].age" value="22"><br>
<h5>vo里的userMap</h5>
<input type="text" name="userMap['u1'].name" value="jack1"><br>
<input type="text" name="userMap['u1'].age" value="31"><br>
<input type="text" name="userMap['u2'].name" value="jack2"><br>
<input type="text" name="userMap['u2'].age" value="32"><br>
<br>
<input type="submit" value="提交">
</form>
@RequestMapping("/complexPojo")
public String pojoParam2(QueryVO vo){
System.out.println(vo);
return "success";
}
中文参数乱码的解决
说明
- 如果请求参数或者响应中有中文,就会乱码。在web阶段,我们通过一个自定义的过滤器实现了统一乱码解决
- 现在SpringMVC本身 ,也给我们提供了一个过滤器
CharacterEncodingFilter
,用于解决乱码问题
解决方案
- 在web.xml中,配置过滤器
CharacterEncodingFilter
<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>
小结
-
- 比如,请求地址:
./req/method3?name=tom&age=20
- Controller里的方法
@RequestMapping("/method3") public String method3(String name, Integer age){ return "success"; }
- 比如,请求地址:
-
如果要把String表单参数,绑定到Date形参上,需要我们定义一个类型转换器
public class MyDateConverter implements Converter<String, Date> { private SimpleDateFormat format = new SimpleDateFormat(); @Override public Date convert(String source) { if (source == null) { // return null; throw new RuntimeException("日期为空,不能转换"); } try { //先尝试以yyyy/MM/dd解析转换 format.applyPattern("yyyy/MM/dd"); return format.parse(source); } catch (ParseException e) {} try { //再尝试以yyyy-MM-dd解析转换 format.applyPattern("yyyy-MM-dd"); return format.parse(source); } catch (ParseException e) { throw new RuntimeException("不支持的日期格式"); } } }
- 在springmvc.xml里注册类型转换器
<!--开启mvc注解驱动--> <mvc:annotation-driven conversion-service="conversionService2"/> <bean id="conversionService2" class="org.springframework.context.support.ConversionServicefactorybean"> <property name="converters"> <set> <bean class="com.guang.converter.MyDateConverter"/> <bean class="自定义的类型转换器的全限定类名"/> </set> </property> </bean>
-
中文请求参数乱码的处理:只需要在web.xml里配置编码过滤器
<!--配置编码过滤器--> <filter> <filter-name>encodingFilter</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>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2. 其它常用注解
@RequestBody
注解@RequestBody
- 语法:
@RequestBody(requried=是否必须有请求体)
- 作用位置:用于方法的参数上,表示把请求体的数据,赋值给方法参数
- 要求:必须是POST方式提交
- 只有POST方式提交,才有请求体;GET方式提交,没有请求体
使用示例
直接接收请求体内容
需求描述
需求实现
- jsp
<form action="${pageContext.request.contextpath}/other/body" method="post">
<input type="text" name="username"><br>
<input type="password" name="password"><br>
<input type="submit" value="post提交">
</form>
- Controller
@RequestMapping("/body")
public String body(@RequestBody String queryString){
System.out.println(queryString);
return "success";
}
接收json格式的请求体
需求描述
- 客户端发Ajax请求,提交json格式的数据
- 服务端接收json格式的数据,直接封装成User对象
前提条件
- pom.xml中添加jackson的依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
- springmvc.xml中,增加配置静态资源的处理
<!--配置静态资源的处理-->
<mvc:default-servlet-handler/>
需求实现
- 把axios拷贝到工程的js文件夹里,如图:
- jsp:使用axios发异步请求
<input type="button" value="Ajax提交json" onclick="submitJson()">
<script src="${pageContext.request.contextpath}/js/axios-0.18.0.js"></script>
<script>
function submitJson() {
var data = {
name:"jack",
age:20
};
axios.post("${pageContext.request.contextpath}/other/body2",data);
}
</script>
- Controller
@RequestMapping("/body2")
public String body2(@RequestBody User user){
System.out.println(user);
return "success";
}
@PathVariable
RESTful编程风格
- REST:Representational State Transfer,是一种编程风格,没有明确的标准。Spring提供的
@PathVariable
,是其支持RESTful风格的一个重要标志 - 特点:
- 资源Resources:每个资源有独一无二的URI
- 表现Representation:资源呈现的形式。例如:文本可以呈现为html、json、xml等等
- 状态转换State Transfer:使用HTTP协议的不同请求方式,表示对资源的不同的操作
- 优点:结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多的网站采用
- 示例:
注解说明
- 作用:Spring3.0提供的,用于获取请求路径中的值,需要配合
@RequestMapping
使用 - 语法:
@PathVariable(value="占位符名称", required=是否必须)
- 作用位置:用在方法参数上,表示获取请求路径中占位符的值,赋值给方法参数
- 例如:
- 客户端请求:
http://localhost:8080/mvc01/delete/100
@RequestMapping("/delete/{id}")
:定义了占位符{id}
@PathVariable("id")
:要获取占位符{id}
位置的值100
- 客户端请求:
使用示例
- jsp
<a href="${pageContext.request.contextpath}/other/pathVar/111">@PathVariable</a><br>
- Controller
@RequestMapping("/pathVar/{id}")
public String pathVar(@PathVariable("id") Integer id){
System.out.println(id);
return "success";
}
@RequestHeader
说明
@H_502_1680@示例- jsp
<a href="${pageContext.request.contextpath}/other/head">@RequestHeader</a><br>
@RequestMapping("/head")
public String header(@RequestHeader("host") String host){
System.out.println(host);
return "success";
}
@CookieValue
说明
示例
- jsp
<a href="${pageContext.request.contextpath}/other/cookie">@CookieValue</a><br>
@RequestMapping("/cookie")
public String cookie(@CookieValue("JSESSIONID") String jSessionId){
System.out.println(jSessionId);
return "success";
}
小结
- 注解@RequestBody:把客户端提交的json格式数据,转换成Java对象,绑定到形参上
<!-- 在pom.xml里增加依赖 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.3</version>
</dependency>
<!-- 页面发异步请求,提交json数据 -->
<input type="button" value="json请求体" onclick="submitJson()">
<script src="js/axios-0.18.0.js"></script>
<script>
function submitJson() {
let data = {
"name":"tom",
"age":20
};
axios.post("./other/body2", data);
}
</script>
//处理器的方法:直接使用@RequestBody接收json数据,转换Java对象,绑定到形参上
@RequestMapping("/body2")
public String body2(@RequestBody User user){
System.out.println(user);
return "success";
}
- 路径变量@PathVariable:用于获取请求uri路径里的变量值
@RequestMapping(value = "/path/{abc}", method = RequestMethod.GET)
public String path(@PathVariable("abc") Integer id){
System.out.println("接收到路径变量值:" + id);
return "success";
}
- 注解@RequestHeader:用于获取请求头的值
@RequestMapping("/header")
public String header(@RequestHeader("User-Agent") String agent){
System.out.println(agent);
return "success";
}
- 注解@CookieValue:用于获取cookie值
@RequestMapping("/cookie")
public String cookie(@CookieValue("JSESSIONID") String jSessionId){
System.out.println(jSessionId);
return "success";
}
3. 使用原始Servlet的API
说明
示例
<a href="${pageContext.request.contextpath}/other/param?name=tom">
提交参数:原生Servlet的API接收
</a>
- Controller
/**
* 用原生Servlet的API,接收客户端提交的参数
*
* @param request 请求对象
*/
@RequestMapping("/param")
public String param1(HttpServletRequest request) {
String username = request.getParameter("username");
System.out.println("用户名:" + username);
return "success";
}
五、数据响应方式【重点】
1. 介绍
2. 页面跳转并传递数据
页面跳转
两种方式介绍
1. 直接返回逻辑视图名称
2. 返回带有前缀的物理视图
- 请求转发:
forward:/success.jsp
- 重定向:
redirect:/success.jsp
- 注意:如果带有
forward
或者redirect
,那么路径必须是真实路径
使用示例
@Controller
@RequestMapping("/demo01")
public class Demo01ResponseController {
@RequestMapping("/forward1")
public String forward1(){
System.out.println("请求转发跳转:由视图解析器拼接成真实路径");
return "success";
}
@RequestMapping("/forward2")
public String forward2(){
System.out.println("请求转发跳转:forward前缀 + 真实路径");
//带有forward前缀的字符串,表示请求转发跳转
return "forward:/success.jsp";
}
@RequestMapping("/redirect")
public String redirect(){
System.out.println("重定向跳转:redirect前缀 + 真实路径");
//带有redirect前缀的字符串,表示重定向跳转
return "redirect:/success.jsp";
}
}
请求转发并传递数据
ModelAndView
说明
ModelAndView
是SpringMVC提供的组件之一,其中Model
,模型,用于封装数据(相当于放到了request域中)View
,视图,用于展示数据
- 如果我们设置了视图名称,并且封装了数据模型,SpringMVC会:
使用示例
- Controller中
/**
* 方法里,我们自己创建ModelAndView
* 设置viewName:视图名称
* 设置view:传递的数据
*/
@RequestMapping("/testModelAndView1")
public ModelAndView testModelAndView1(){
ModelAndView modelAndView = new ModelAndView();
//设置封装数据
modelAndView.addobject("username", "itcast");
//设置视图名称
modelAndView.setViewName("success");
return modelAndView;
}
/**
* 让框架提供一个ModelAndView,我们设置viewName和Model数据
*/
@RequestMapping("/testModelAndView2")
public ModelAndView testModelAndView2(ModelAndView modelAndView){
//设置封装数据
modelAndView.addobject("username", "guang");
//设置视图名称
modelAndView.setViewName("success");
return modelAndView;
}
/**
* 让框架提供Model,用于封装数据
* 我们返回一个String:是视图名称
*/
@RequestMapping("/testModelAndView3")
public String testModelAndView3(Model model){
//设置封装数据
model.addAttribute("username", "javaee");
//返回视图名称
return "success";
}
/**
* 让框架提供request对象,我们向request域中存储数据
* 方法返回字符串,是视图名称
*/
@RequestMapping("/testModelAndView4")
public String testModelAndView4(HttpServletRequest request){
//设置封装数据
request.setAttribute("username", "Boxuegu");
//返回视图名称
return "success";
}
<h1>success!${username}</h1>
小结
- 方法返回
ModelAndView
public ModelAndView jump(){
ModelAndView mav = new ModelAndView();
mav.setViewName("视图名称");
mav.addobject("数据名称", "值");
return mav;
}
public ModelAndView jump(ModelAndView mav){
mav.setViewName("视图名称");
mav.addobject("数据名称", "值");
return mav;
}
public String jump(Model model){
model.addAttribute("数据名称", "值");
return "视图名称";
}
public String jump(Map model){
model.addAttribute("数据名称", "值");
return "视图名称";
}
3. 直接返回响应数据
通常用于客户端是Ajax请求的时候,给Ajax引擎返回数据
直接响应字符串
两种方式介绍
- 使用Servlet原生的
response
对象,返回响应数据 - 使用
@ResponseBody
注解,把方法返回值声明成要返回的数据
使用示例
/**
* 使用Servlet原生的response对象,设置要响应的数据。《不建议使用》
* 注意:方法不需要返回值了
*/
@RequestMapping("/responseBody1")
public void responseBody1(HttpServletResponse response) throws IOException {
response.getWriter().print("response");
}
/**
* 方法返回String,但是使用注解@ResponseBody把字符串声明成返回的内容,而不是视图
*/
@RequestMapping("/responseBody2")
@ResponseBody
public String responseBody2(){
return "hello, mvc";
}
拓展
- 如果使用
@ResponseBody
响应的中文字符串,即使配置了CharacterEncodingFilter
,也会有乱码 - 解决方法:在
springmvc.xml
里配置如下:- 配置SpringMVC的
StringHttpMessageConverter
进行字符串处理转换,设置采用utf-8
字符集
- 配置SpringMVC的
<!--开启mvc的注解驱动-->
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="defaultCharset" value="utf-8"/>
<property name="supportedMediaTypes">
<set>
<value>text/plain;charset=utf-8</value>
<value>text/html;charset=utf-8</value>
<value>application/json;charset=utf-8</value>
</set>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
响应json格式
两种方式介绍
- 自己把JavaBean对象转换成json格式的字符串,响应给客户端
- 方法返回JavaBean对象,使用
@ResponseBody
注解让框架帮我们转换成json格式
前提条件
- 在pom.xml中导入依赖:
jackson-databind
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
使用示例
/**
* 我们自己把Java对象转换成json格式的字符串
* 使用注解@ResponseBody,告诉Spring返回的字符串 是要响应的数据
*/
@RequestMapping("/responseBody2")
@ResponseBody
public String responseBody2() throws Exception{
User user = new User();
user.setUsername("tom");
user.setAge(20);
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsstring(user);
}
/**
* 方法返回Java对象,使用注解@ResponseBody让框架帮我们转换成json格式
* 注意:
* 1. 必须在springmvc.xml中开启了mvc的注解驱动:<mvc:annotation-driven/>
* 2. 必须导入了依赖:jackson-databind
*/
@RequestMapping("/responseBody4")
@ResponseBody
public User responsebody4(){
User user = new User();
user.setUsername("tom");
user.setAge(20);
return user;
}
小结
- 如果要直接响应数据,使用response对象
public void method1(HttpServletResponse response){
//如果响应普通文本数据
//response.setContentType("text/html;charset=utf-8");
//如果响应json格式的字符串
response.setContentType("application/json;charset=utf-8");
response.getWriter().print("xxxx");
}
- 如果要响应json数据,方法直接返回JavaBean对象
@RequestMapping("/method2")
@ResponseBody
public User method2(){
return new User();
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。