一、SpringMVC的基本概念
(一)三层架构和MVC
1、三层架构概述
我们的开发架构一般都是基于两种形式,一种是 C/S 架构,也就是客户端/服务器,另一种是 B/S 架构,也就是浏览器服务器。在 JavaEE 开发中,几乎全都是基于 B/S 架构的开发。那么在 B/S 架构中,系统标准的三层架构包括:表现层、业务层、持久层。三层架构在我们的实际开发中使用的非常多,所以我们课程中的案例也都是基于三层架构设计的。
三层架构中,每一层各司其职,接下来我们就说说每层都负责哪些方面:
(1)表现层:也就是我们常说的web层。它负责接收客户端请求,向客户端响应结果,通常客户端使用http协议请求web 层,web 需要接收 http 请求,完成 http 响应。
表现层包括展示层和控制层:控制层负责接收请求,展示层负责结果的展示。
(2)业务层:也就是我们常说的 service 层。它负责业务逻辑处理,和我们开发项目的需求息息相关。
(3)持久层:也就是我们是常说的 dao 层。负责数据持久化,和数据库做交互。
2、model1模式介绍
这种模式十分简单,页面显示,控制分发,业务逻辑,数据访问全部通过Jsp去实现
3、model2模式介绍
这种模式通过两部分去实现,即Jsp与Servlet。Jsp负责页面显示,Servlet负责控制分发,业务逻辑以及数据访问。
4、MVC模式介绍
MVC模式则分为三大块,即视图(View),控制器(Control),模型(Model).视图是Jsp负责的页面显示,控制器则是Servlet负责的控制分发,模型包括Service和Dao两个部分,分别负责业务逻辑和数据访问。
5、三种模型对比
Model1 模式的优缺点:
优点:架构简单,比较适合小型项目开发
缺点:JSP 职责不单一,职责过重,不便于维护
Model2 模式的优缺点:
优点:职责清晰,较适合于大型项目架构
缺点:不适合小型项目开发
MVC模式的优缺点:
优点:分工明确,各司其职,互不干涉。适用于大型项目架构,有利于组件的重构
缺点:增加了系统开发的复杂度
(二)SpringMVC 概述
1、springMVC是什么?
SpringMVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。它通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口。同时它还支持RESTful编程风格的请求。
2、SpringMVC在三层架构中的位置?
springMVC位于三层架构中的表现层,作用是接收请求响应数据,响应的数据通过视图、模板展示给用户。
3、SpringMVC的优势?
(1)清晰的角色划分:
前端控制器(DispatcherServlet)
请求到处理器映射(HandlerMapping)
处理器适配器(HandlerAdapter)
视图解析器(ViewResolver)
处理器或页面控制器(Controller)
验证器(Validator)
命令对象(Command 请求参数绑定到的对象就叫命令对象)
表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)。
(2)分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要。
(3)由于命令对象就是一个POJO,无需继承框架特定 API,可以使用命令对象直接作为业务对象。
(4)和 Spring 其他框架无缝集成,是其它 Web 框架所不具备的。
(5)可适配,通过 HandlerAdapter 可以支持任意的类作为处理器。
(6)可定制性,HandlerMapping、ViewResolver 等能够非常简单的定制。
(7)功能强大的数据验证、格式化、绑定机制。
(8)利用 Spring 提供的 Mock 对象能够非常简单的进行 Web 层单元测试。
(9)本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。
(10)强大的 JSP 标签库,使 JSP 编写更容易。
………………还有比如RESTful风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配置支持等等。
二、SpringMVC入门
(一)SpringMVC 的入门案例
1、入门案例需求分析
构建页面index.jsp发起请求,在服务器端处理请求,控制台打印处理请求成功,跳转main.jsp成功页面;
2、构建maven项目并添加依赖
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jn</groupId>
<artifactId>SpringMVC01</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>SpringMVC01 Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!--spring-webmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.4</version>
</dependency>
<!--spring-web-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.4</version>
</dependency>
<!--spring-context-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.4</version>
</dependency>
</dependencies>
</project>
3、在web-app目录下配置index.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="/hello/test1"></a>
</body>
</html>
4、在web-app目录下配置跳转页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>请求处理成功</h2>
</body>
</html>
5、web.xml中配置核心控制器DispatcherServlet
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<!-- 配置Spring MVC的前端控制器 -->
<servlet>
<!-- servlet的名称 -->
<servlet-name>spring-mvc</servlet-name>
<!-- servlet的类路径,指向Spring的请求分发器 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 初始化参数,指定Spring MVC配置文件的位置 -->
<init-param>
<!-- 参数名称:配置文件位置 -->
<param-name>contextConfigLocation</param-name>
<!-- 参数值:配置文件在类路径下的位置 -->
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<!-- 配置spring-mvc servlet的URL映射规则 -->
<servlet-mapping>
<!-- 对应的servlet名称 -->
<servlet-name>spring-mvc</servlet-name>
<!-- URL模式,匹配以.do结尾的请求 -->
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
6、配置springMVC的配置文件springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--扫描注解的包-->
<context:component-scan base-package="com.jn.controller"/>
<!--处理映射器:根据请求路径匹配映射路径找到对应的执行器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
</bean>
<!--处理适配器:根据处理映射器返回的执行器对象去执行执行器对象-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
</bean>
<!--视图解析器:解析视图-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
7、控制层controller
package com.jn.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping("hello")
public String test1(){
System.out.println("请求处理成功");
return "RequestSuccessful";
}
}
8、测试
启动tomcat进行测试 ,然后点击hello超链接跳转到成功页面。
注意:使用tomcat10以上版本会报错,所以本次测试使用的是tomcat8版本
(二)SpringMVC执行过程及原理分析
1、案例的执行过程
浏览器客户端发起请求,请求到达服务器tomcat,tomcat将请求相关信息参数封装到对象request和response中,再将request和response对象交给service方法处理,在service方法中会根据请求路径将请求交给对应的controller执行器处理。
2、SpringMVC的请求响应流程
浏览器发送请求,被DispatcherServlet捕获,DispatcherServlet没有直接处理请求,而是将请求交给HandlerMapping处理器映射器,处理器映射器根据请求路径去controller控制层中匹配对应的执行器,并将匹配结果返回给DispatcherServlet,由DispacherServlet调用HandlerAdapter处理器适配器来执行控制层执行器方法;
执行器方法执行后的返回结果,由DispatcherServlet交给视图解析器ViewResolver来处理,找到对应的结果视图,渲染视图,并将结果响应给浏览器。
(三)SpringMVC常用组件介绍
1、DispatcherServlet:前端控制器
用户请求到达前端控制器,它就相当于 mvc 模式中的 c,dispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet 的存在降低了组件之间的耦合性。
2、HandlerMapping:处理器映射器
HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
3、Handler:处理器
它就是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由Handler 对具体的用户请求进行处理。
4、HandlAdapter:处理器适配器
通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
5、View Resolver:视图解析器
View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。
6、View:视图
SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是 jsp。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
7、mvc:annotation-driven标签说明:
在 SpringMVC 的各个组件中,处理器映射器、处理器适配器、视图解析器称为 SpringMVC 的三大组件。使用 <mvc:annotation-driven> 自动加载 RequestMappingHandlerMapping(处理映射器)和RequestMappingHandlerAdapter ( 处 理 适 配 器 ),可 用 在 SpringMVC.xml 配 置 文 件 中 使 用<mvc:annotation-driven>替代处理映射器和适配器的配置(一般开发中都需要该标签)。注意:我们只需要编写处理具体业务的控制器以及视图。
<mvc:annotation-driven> 标签相当于以下配置:
<!--处理映射器:根据请求路径匹配映射路径找到对应的执行器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
</bean>
<!--处理适配器:根据处理映射器返回的执行器对象去执行执行器对象-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
</bean>
(四)RequestMapping 注解
用于定义映射路径,建立请求url和控制层方法之间的对应关系;
1、RequestMapping 注解源码解读
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
String name() default "";
@AliasFor("path")
String[] value() default {};
@AliasFor("value")
String[] path() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
}
2、RequestMapping 注解的描述
(1)注解位置:
a.类上:定义一级映射路径;
b.方法上:定义二级映射路径;
(2)注解属性:
value:用于指定映射路径url。它和 path 属性的作用是一样的。
method:用于指定请求的方式。
params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和配置的一模一样。eg:params = {"username"},表示请求参数必须有 username;
headers:用于指定限制请求消息头的条件。
注意:多个属性之间是与的关系;
三、SpringMVC中的请求参数绑定
(一)绑定说明
1、绑定的机制
我们都知道,表单中请求参数都是基于 key=value 的。SpringMVC绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定的。
2、支持的数据类型
基本类型参数:包括基本类型和 String 类型
POJO 类型参数:包括实体类,以及关联的实体类
数组和集合类型参数:包括 List 结构和 Map 结构的集合(包括数组)
3、使用要求:
如果是基本类型或者 String 类型:要求我们的参数名称必须和控制器中方法的形参名称保持一致。(严格区分大小写)
如果是 POJO 类型,或者它的关联对象:要求表单中参数名称和 POJO 类的属性名称保持一致。并且控制器方法的参数类型是 POJO 类型。
如果是集合类型,有两种方式:
(1)第一种:要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同。给 List 集合中的元素赋值,使用下标。给 Map 集合中的元素赋值,使用键值对。
(2)第二种:接收的请求参数是 json 格式数据。需要借助一个注解实现。
(二)参数绑定示例
1、基本类型和 String 类型作为参数
(1)页面定义请求:
<form action="stringTest" method="post">
name :<input type="text" name="name"><br>
age :<input type="text" name="age"><br>
<input type="submit" value="提交">
</form>
(2)执行器方法绑定参数:
//测试String类型作为参数
@RequestMapping("stringTest")
public String testString(String name,int age){
System.out.println("name:" + name);
System.out.println("age:" + age);
return "RequestSuccessful";
}
2、POJO 类型作为参数
(1)实体类创建:
Car:
package com.jn.pojo;
public class Car {
private String name;
private int price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return "Car{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
User:
package com.jn.pojo;
public class User {
private String name;
private int age;
private Car car;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", car=" + car +
'}';
}
}
(2)页面定义请求:
<div>
<form action="pojoTest">
name :<input type="text" name="name"><br>
age :<input type="text" name="age"><br>
carName :<input type="text" name="car.name"><br>
carPrice :<input type="text" name="car.price"><br>
<input type="submit" value="提交">
</form>
</div>
(3)执行器方法绑定参数:
//测试Pojo类型作为参数
@RequestMapping("pojoTest")
public String testPojo(User user){
System.out.println(user);
return "RequestSuccessful";
}
3、POJO 类中包含集合类型参数
(1)User类修改
package com.jn.pojo;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class User {
private String name;
private int age;
private Car car;
private List<Car> carList;
private Set<Car> carSet;
private HashMap<String,Car> carMap;
User(){
//初始化set集合
carSet=new HashSet<>();
Car car = new Car();
Car car1=new Car();
carSet.add(car);
carSet.add(car1);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public List<Car> getCarList() {
return carList;
}
public void setCarList(List<Car> carList) {
this.carList = carList;
}
public Set<Car> getCarSet() {
return carSet;
}
public void setCarSet(Set<Car> carSet) {
this.carSet = carSet;
}
public HashMap<String, Car> getCarMap() {
return carMap;
}
public void setCarMap(HashMap<String, Car> carMap) {
this.carMap = carMap;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", car=" + car +
", carList=" + carList +
", carSet=" + carSet +
", carMap=" + carMap +
'}';
}
}
(2)页面定义请求:
<div>
<form action="listTest">
name :<input type="text" name="name"><br>
age :<input type="text" name="age"><br>
carName :<input type="text" name="car.name"><br>
carPrice :<input type="text" name="car.price"><br>
listCarName :<input type="text" name="carList[0].name"><br>
listCarPrice :<input type="text" name="carList[0].price"><br>
listCarName1 :<input type="text" name="carList[1].name"><br>
listCarPrice1 :<input type="text" name="carList[1].price"><br>
setCarName :<input type="text" name="carSet[0].name"><br>
setCarPrice :<input type="text" name="carSet[0].price"><br>
setCarName1 :<input type="text" name="carSet[1].name"><br>
setCarPrice1 :<input type="text" name="carSet[1].price"><br>
mapCarName :<input type="text" name="carMap['x'].name"><br>
mapCarPrice :<input type="text" name="carMap['x'].price"><br>
mapCarName1 :<input type="text" name="carMap['y'].name"><br>
mapCarPrice1 :<input type="text" name="carMap['y'].price"><br>
<input type="submit" value="提交">
</form>
</div>
(3)执行器方法绑定参数:
//测试List类型作为参数
@RequestMapping("listTest")
public String testList(User user){
System.out.println(user);
return "RequestSuccessful";
}
4、数组类型参数
(1)页面定义请求:
<div>
<form action="arrTest">
hobby1 :<input type="text" name="hobbies" ><br>
hobby2 :<input type="text" name="hobbies" ><br>
hobby3 :<input type="text" name="hobbies" ><br>
hobby4 :<input type="text" name="hobbies" ><br>
<input type="submit" value="提交">
</form>
</div>
(2)执行器方法绑定参数:
//测试数组类型作为参数
@RequestMapping("arrTest")
public String testArray(String[] hobbies){
for (String hobby : hobbies) {
System.out.println(hobby);
}
return "RequestSuccessful";
}
5、使用 ServletAPI 对象作为方法参数
(1)引入servletAPI的依赖jar包
(注意jar包作用范围provided:不参与项目部署)
<!--servlet-api依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
(2)执行器方法绑定参数
浏览器启动时直接访问servletTest然后就能进行跳转到hello
//servlet API对象作为返回参数
@RequestMapping("servletTest")
public void testServlet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//转发到/test1
System.out.println("正在请求转发");
request.getRequestDispatcher("/hello").forward(request,response);
}
6、请求参数乱码问题
tomacat 对 GET 和 POST 请求处理方式是不同的:
(1)GET 请求的编码问题,要改 tomcat 的 server.xml配置文件:
进行修改:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8"/>
(2)POST 请求的编码问题,要在web.xml文件中配置编码过滤器:
在进行过滤器添加的时候报错The content of element type "web-app" must match "(icon?,display-name?,description?,distributable?,context-param*,filter*,filter-mapping*,listener*,servlet*,servlet-mapping*,session-config?,mime-mapping*,welcome-file-list?,error-page*,taglib*,resourc。最后发现是DOM树里面的元素<head> 版本不匹配,我们改为以下配置就行:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
</web-app>
然后加入过滤器:
<!--配置post请求时的编码过滤器-->
<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>
7、静态资源访问:
静态资源的配置有两种方式,下面的两种配置方式任选一种配置就行
(1)将静态资源交给默认的DefaultServlet处理
在springMVC.xml配置文件中加如下配置:
<!--开启静态资源配置-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
(2)指定静态资源的访问路径:
在springMVC.xml配置文件中加如下配置:
<!--开启静态资源配置 第二种方式-->
<mvc:resources mapping="/images/**" location="/images/"/>
(3)web-app目录下新建images存入图片
(4)index.jsp配置显示静态路径图片
<div>
<img src="./images/girls.jpg">
</div>
(5)测试
图片正常显示
(三)自定义参数处理
1、使用场景:
SpringMVC不能自动识别参数转换为我们需要的数据类型,浏览器报400错误,类型转换异常;
2、使用步骤:
(1)定义类型转换器
package com.jn.utils;
import org.springframework.core.SimpleAliasRegistry;
import org.springframework.core.convert.converter.Converter;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
定义类型转化器
定义了一个名为 MyDateConverter 的类,该类实现了 Converter<String, Date> 接口。
主要功能是将字符串格式的日期转换为 Date 对象。
*/
public class MyDateConverter implements Converter<String, Date> {
@Override
public Date convert(String s) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = sdf.parse(s);
} catch (Exception e) {
e.printStackTrace();
}
return date;
}
}
(2)配置类型转换器
<!--配置类型转换器
将自定义的 MyDateConverter 注册到 Spring 的类型转换服务中,使得在应用中可以使用 MyDateConverter 来进行字符串到日期的转换。-->
<bean id="formattingConversionServiceFactoryBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<bean class="com.jn.utils.MyDateConverter"></bean>
</property>
</bean>
(3)引用类型转换器
1.页面定义请求
//测试自定义类型转换器
@RequestMapping("typeChange")
public String testDate(Date birthday){
System.out.println(birthday);
return "RequestSuccessful";
}
2. 执行器方法绑定参数:
//测试自定义类型转换器
@RequestMapping("typeChange")
public String testDate(Date date){
System.out.println(date);
return "RequestSuccessful";
}
3.发现错误
Failed to convert value of type 'java.lang.String' to required type 'java.util.Date'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.util.Date': no matching editors or conversion strategy found
然后死活不知道怎么修改这个错误,最后折腾了半个小时发现只要早controller里面加入配置函数运行就好了。
@InitBinder
protected void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
四、SpringMVC的注解详解
(一)RequestParam
1、RequestParam注解介绍
使用在方法入参位置,用于指定请求参数名称,将该请求参数绑定到注解参数位置。
属性:name:指定要绑定的请求参数名称;
required:指定请求参数是否必传;
defaultValue:指定当没有传入请求参数时的默认取值;
2、RequestParam注解使用案例
//测试RequestParam注解测试
@RequestMapping("requestParam")
public String testRequestParam(@RequestParam("username") String name){
System.out.println("name:" + name);
return "RequestSuccessful";
}
3、RequestParam注解测试结果
启动Tmocat 输入:
http://localhost:8080/SpringMVC01_war_exploded/requestParam?username=hhh
(二)RequestHeader
1、RequestHeader注解介绍
注解在方法入参位置,用于获取请求头信息。
2、RequestHeader注解使用案例
//测试RequestHeader注解
@RequestMapping("requestHeader")
public String testRequestHeader(@RequestHeader("User-Agent") String header){
System.out.println("header:" + header);
return "RequestSuccessful";
}
3、RequestHeader注解测试结果
(三)RequestBody
1、RequestBody注解介绍
用于方法入参位置,获取请求体内容。直接使用得到是 key=value&key=value...结构的数据。get 请求方式不适用。通常用于将json格式字符串绑定到bean对象中;
2、RequestBody注解案例
(1)直接获取请求体内容
<div>
<form action="typeChange">
birthday :<input type="date" name="birthday"><br>
<input type="submit" value="提交">
</form>
</div>
//测试requestBody
@RequestMapping("requestBody")
public String testRequestBody(@RequestBody String body){
System.out.println(body);
return "RequestSuccessful";
}
(2)将json格式请求参数绑定到指定对象bean中
新建jsp页面实现ajax请求:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script>
//页面加载时间
$(function () {
//为按钮绑定点击事件
$("#btn").click(function () {
$.ajax({
url:"ajaxTest",
data:'{"name":"Tom","age":18}',
type:"POST",
contentType:"application/json",
success:function (obj) {
//将控制层操作成功响应信息通过弹窗展示
alert(obj);
},
})
})
})
</script>
</head>
<body>
<button id="btn">发送ajax请求</button>
</body>
</html>
RequestBody注册使用案例:
//测试json对象的RequestBody
@RequestMapping("ajaxTest")
public String testRequestBodyJson(@RequestBody String car){
System.out.println(car);
return "RequestSuccessful";
}
3、RequestBody注解测试结果
(四)CookieValue
1、CookieValue注解介绍
用于方法入参位置,把指定 cookie 名称的值传入控制器方法参数。
2、CookieValue注解使用案例
//CookieValue注解使用案例
@RequestMapping("cookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String cookie){
System.out.println(cookie);
return "RequestSuccessful";
}
3、CookieValue注解测试结果
(五)ModelAttribute
1、ModelAttribute注解介绍
该注解是SpringMVC4.3版本以后新加入的。它可以用于修饰方法和参数。出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。出现在参数上,获取指定的数据给参数赋值。
2、ModelAttribute注解使用案例
(1)注解在方法上:
//ModelAttribute注解用于方法 用来绑定一个公共的参数sharParam
@ModelAttribute("sharParam")
public String testModelAttribute(){
System.out.println("我是公共参数");
return "公共参数";
}
(2)注解在参数位置:
//测试ModelAttribute注解用于参数
@RequestMapping("modelAttribute")
public String testModelAttribute(@ModelAttribute("sharParam") String modelAttribute){
System.out.println("modelAttribute:" + modelAttribute);
return "RequestSuccessful";
}
3、ModelAttribute注解测试结果
(六)SessionAttributes
1、SessionAttributes注解介绍
注解在类上,作用将请求域中的参数存放到session域中,用于参数共享。
2、将参数放入Session请求域
//将请求对象放入到请求域
@RequestMapping("requestAttribute")
public ModelAndView testRequestAttribute(HttpServletRequest request, ModelAndView mv){
mv.addObject("aa","AA");
mv.addObject("bb","BB");
mv.addObject("cc","CC");
HttpSession session = request.getSession();
session.setAttribute("aa", "AA");
session.setAttribute("bb", "BB");
session.setAttribute("cc", "CC");
mv.setViewName("RequestSuccessful");
return mv;
}
3、 将参数放入到Session作用域
package com.jn.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@Controller
@SessionAttributes(value = {"aa","bb"})
public class SessionAttributeTest {
// 从Session中获取属性并添加到模型,用于在另一个请求中展示
@RequestMapping("/getSessionAttributes")
public String getSessionAttributes(HttpServletRequest request, Model model) {
// 从 Session 中获取属性
HttpSession session = request.getSession();
String aaFromSession = (String) session.getAttribute("aa");
String bbFromSession = (String) session.getAttribute("bb");
String ccFromSession = (String) session.getAttribute("cc");
// 将 Session 中的属性添加到模型中
model.addAttribute("aaFromSession", aaFromSession);
model.addAttribute("bbFromSession", bbFromSession);
model.addAttribute("ccFromSession", ccFromSession);
return "sessionAttributesShow";
}
}
4、请求成功页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>设置Session属性后的结果页面</h2>
<p>属性aa的值:${aa}</p>
<p>属性bb的值:${bb}</p>
<p>属性cc的值:${cc}</p>
</body>
</html>
3、SessionAttributes注解测试结果