文章目录
1 Spring MVC 介绍
1.1 MVC模型
MVC全名是Model View Controller 模型视图控制器,每个部分各司其职。
- Model:数据模型,JavaBean的类,用来进行数据封装。
- View:指JSP、HTML用来展示数据给用户
- Controller:用来接收用户的请求,整个流程的控制器。用来进行数据校验等。
1.2 Spring MVC
Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。
Spring MVC主要由前端映射器DispatcherServlet、处理器映射器HandlerMapping、处理器适配器HandlAdapter、处理器Handler、视图解析器View Resolver、视图View组成。
两个核心:
处理器映射器:选择使用哪个控制器来处理请求
视图解析器:选择结果应该如何渲染
2 Spring MVC处理请求流程
2.1 流程介绍
第一步:用户发送请求到前端控制器(DispatcherServlet)。
第二步:前端控制器请求处理器映射器 HandlerMapping 查找 Handler,可以根据 xml 配置、注解进行查找。
第三步:处理器映射器 HandlerMapping 向前端控制器返回 Handler
第四步:前端控制器调用处理器适配器去执行 Handler
第五步:处理器适配器执行 Handler
第六步:Handler 执行完成后给适配器返回 ModelAndView
第七步:处理器适配器向前端控制器返回 ModelAndView
ModelAndView 是SpringMVC 框架的一个底层对象,包括 Model 和 View
第八步:前端控制器请求试图解析器去进行视图解析
根据逻辑视图名来解析真正的视图。
第九步:视图解析器向前端控制器返回 view
第十步:前端控制器进行视图渲染
就是将模型数据(在 ModelAndView 对象中)填充到 request 域
第十一步:前端控制器向用户响应结果
2.2 组件介绍
1、前端控制器DispatcherServlet(不需要程序员开发)。
作用:接收请求,响应结果,相当于转发器,中央处理器。有了DispatcherServlet减少了其它组件之间的耦合度。
2、处理器映射器HandlerMapping(不需要程序员开发)。
作用:HandlerMapping 负责根据用户请求的url找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
3、处理器适配器HandlerAdapter(不需要程序员开发)。
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler。
4、处理器Handler(需要程序员开发)。
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
5、视图解析器ViewResolver(不需要程序员开发)。
作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)
6、视图View(需要程序员开发jsp)。
注意:View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)
注意:不需要程序员开发的,需要程序员自己做一下配置即可。
可以总结出:需要我们开发的工作只有处理器** Handler 的编写以及视图**比如JSP页面的编写。
3 SpringMVC的入门案例
1. SpringMVC的入门程序
1.1 WEB工程结构
1.2 创建WEB工程,引入的依赖
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.pikaqiu</groupId>
<artifactId>SpringMVC_InitalCase</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>SpringMVC_InitalCase Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>SpringMVC_InitalCase</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
1.3 配置核心的控制器(配置DispatcherServlet)
在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>
<display-name>Archetype Created Web Application</display-name>
<!--配置核心控制器DispatcherServle-->
<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:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
1.4 编写springmvc.xml的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解扫描-->
<context:component-scan base-package="com.pikaqiu"></context:component-scan>
<!--视图解析器-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--开启SpringMVC框架注解的支持-->
<!--会自动注册RequestMappingHandlerMapping与RequestMappingHandlerAdapter两个Bean-->
<mvc:annotation-driven/>
</beans>
注意:mvc:annotation-driven/的作用
它就相当于在 xml 中配置了:
<!-- 上面的标签相当于 如下配置-->
<!-- Begin -->
<!-- HandlerMapping -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerM
apping"></bean>
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- HandlerAdapter -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerA
dapter"></bean>
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean> <bean
class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- HadnlerExceptionResolvers -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExcept
ionResolver"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolv
er"></bean>
<bean class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver"
></bean>
<!-- End -->
1.5 编写index.jsp和Controller控制器类
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>入门程序</h3>
<a href="hello">入门程序</a>
</body>
</html>
package com.pikaqiu;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author pikaqiu
* @description: TODO 类描述
* @date: 2022/3/26 14:49
**/
@Controller
public class HelloController {
@RequestMapping(path = "/hello")
public String sayHello(){
System.out.println("hello SpringMVC");
return "success";
}
}
1.6 在WEB-INF目录下创建pages文件夹,编写success.jsp的成功页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>入门成功</h3>
</body>
</html>
1.7 Tomcat配置
1.8 启动Tomcat
1.9 入门案例的执行过程分析
- 当启动Tomcat服务器的时候,因为配置了load-on-startup标签,所以会创建DispatcherServlet对象, 就会加载springmvc.xml配置文件
- 开启了注解扫描,那么HelloController对象就会被创建
- 从index.jsp发送请求,请求会先到达DispatcherServlet核心控制器,根据配置@RequestMapping注解 找到执行的具体方法
- 根据执行方法的返回值,再根据配置的视图解析器,去指定的目录下查找指定名称的JSP文件
- Tomcat服务器渲染页面,做出响应
4 请求参数的绑定
4.1 请求参数的绑定说明
4.1.1 绑定机制
1️⃣ 表单提交的数据都是k=v格式的 username=haha&password=123
2️⃣ SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的
3️⃣ 要求:提交表单的name和参数的名称是相同的
4.1.2 支持的数据类型
1️⃣ 基本数据类型和String类型
2️⃣ POJO类型(包括实体类,以及关联的实体类)
3️⃣ 数组和集合数据类型(List、map集合等)
4.2 基本数据类型和String类型
1️⃣ 提交表单的name和参数的**名称是相同**的
2️⃣ 严格区分大小写
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="param/testBasicParamAndString?userName=zhangsan&age=23">基本类型和String类型请求参数绑定</a>
</body>
</html>
package com.pikaqiu;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/testBasicParamAndString")
public String testBasicParamAndString(String userName, Integer age){
System.out.println("正常运行");
System.out.println("userName: " + userName + " age: " + age);
return "success";
}
}
4.3 POJO类型(JavaBean)
1️⃣ 提交表单的name和JavaBean中的**属性名称需要一致**
2️⃣ 如果一个JavaBean类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性 例 如: address.name
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="param/testPoJO" method="post">
姓名:<input type="text" name="userName"><br/>
密码:<input type="text" name="passWord"><br/>
工资:<input type="text" name="money"><br/>
uName:<input type="text" name="user.uName"><br/>
uAge:<input type="text" name="user.uAge"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/testPoJO")
public String testPOJOParam(Account account){
System.out.println("正常运行");
System.out.println(account);
return "success";
}
}
4.4 集合类型
第一种:
要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同。
给 List 集合中的元素赋值,使用下标。
给 Map 集合中的元素赋值,使用键值对。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="param/testListAndMap" method="post">
姓名:<input type="text" name="userName"><br/>
密码:<input type="text" name="passWord"><br/>
工资:<input type="text" name="money"><br/>
用户姓名:<input type="text" name="uList[0].uName"><br/>
用户年龄:<input type="text" name="uList[0].uAge"><br/>
用户姓名:<input type="text" name="uList[1].uName"><br/>
用户年龄:<input type="text" name="uList[1].uAge"><br/>
用户姓名:<input type="text" name="uMap['one'].uName"><br/>
用户年龄:<input type="text" name="uMap['one'].uAge"><br/>
用户姓名:<input type="text" name="uMap['two'].uName"><br/>
用户年龄:<input type="text" name="uMap['two'].uAge"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/testListAndMap")
public String test(Account account)
{
System.out.println("正常运行");
System.out.println(account);
return "success";
}
}
第二种:
接收的请求参数是 json 格式数据。需要借助一个注解实现。(@ResponseBody)
4.5 请求参数中文乱码的解决
post请求: 在web.xml中配置Spring提供的过滤器类
<!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>
<display-name>Archetype Created Web Application</display-name>
<!--配置中文乱码过滤器-->
<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>
<!--配置核心控制器DispatcherServle-->
<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:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
**get请求:tomacat 对 GET 和 POST 请求处理方式是不同的,GET 请求的编码要改 tomcat 的server.xml **
配置文件
改为:
如果遇到 ajax 请求仍然乱码,请把:
useBodyEncodingForURI="true"改为 URIEncoding=“UTF-8”
即可。
4.6 自定义类型转换器
1.表单提交的任何数据类型全部都是字符串类型,但是后台定义Integer类型,数据也可以封装上,说明 Spring框架内部会默认进行数据类型转换。
2.如果想自定义数据类型转换,可以实现Converter的接口
4.6.1 自定义类型转换器
package com.pikaqiu.util;
import org.springframework.core.convert.converter.Converter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 把字符串转换为日期
**/
public class StringToDateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
if(source == null){
throw new RuntimeException("请您传入数据");
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
// 把字符串转为日期
try {
return df.parse(source);
} catch (ParseException e) {
throw new RuntimeException("数据类型转换出现错误");
}
}
}
4.6.2 注册自定义类型转换器,在springmvc.xml配置文件中编写配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解扫描-->
<context:component-scan base-package="com.pikaqiu"></context:component-scan>
<!--视图解析器-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--配置自定义类型转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.pikaqiu.util.StringToDateConverter"></bean>
</set>
</property>
</bean>
<!--开启SpringMVC框架注解的支持-->
<!--会自动注册RequestMappingHandlerMapping与RequestMappingHandlerAdapter两个Bean-->
<mvc:annotation-driven conversion-service="conversionService"/>
</beans>
4.6.3 param.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="param/testSelfConverter" method="post">
姓名:<input type="text" name="uName"><br/>
年龄:<input type="text" name="uAge"><br/>
生日:<input type="text" name="birthDay"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
4.6.4 Controller类
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/testSelfConverter")
public String testSelfConverter(User user)
{
System.out.println("正常运行");
System.out.println(user);
return "success";
}
}
4.7 控制器使用原生的ServletAPI对象
只需要在控制器的方法参数定义HttpServletRequest和HttpServletResponse对象
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="param/testServlet?username=haha&password=123">Servlet原生的API</a>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
public class ParamController {
/**
* 使用Servlet原生的API
* @param
* @return
*/
@RequestMapping("/testServlet")
public String testServlet(HttpServletRequest request, HttpServletResponse response){
System.out.println("正常运行");
System.out.println(request);
HttpSession session = request.getSession();
System.out.println(session);
ServletContext servletContext = session.getServletContext();
System.out.println(servletContext);
System.out.println(response);
return "success";
}
}
5 常用注解
5.1 RequestParam注解
1️⃣ 作用:把请求中的指定名称的参数传递给控制器中的形参赋值
2️⃣ 属性
value:请求参数中的名称
required:请求参数中是否必须提供此参数,默认值是true,必须提供
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="param/testRequestParam?username=haha&password=123">RequestParam注解</a>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
public class ParamController {
/**
* @RequestParam注解
*/
@RequestMapping("/testRequestParam")
public String testRequestParam(@RequestParam(name = "username") String username, @RequestParam(name = "password") String password){
System.out.println("正常运行");
System.out.println(username);
System.out.println(password);
return "success";
}
}
注意:AnnoController类中 @RequestParam(name = “name”),name的值与 href="anno/testRequestParam?name=哈哈"中 name值一致。
5.2 RequestBody注解
1️⃣ 作用:用于获取请求体的内容(注意:get方法不可以)
2️⃣ 属性
required:是否必须有请求体,默认值是true
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="param/testRequestBody" method="post">
用户姓名:<input type="text" name="uname"><br/>
用户年龄:<input type="text" name="uage"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
public class ParamController {
/**
* @RequestBody注解
*/
@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody(required=false) String body){
System.out.println("正常运行");
System.out.println(body);
return "success";
}
}
5.3 PathVariable注解
1️⃣ 作用:拥有绑定url中的占位符的。例如:url中有/delete/{id},{id}就是占位符
2️⃣ 属性
value:指定url中的占位符名称
3️⃣ Restful风格的URL
①请求路径一样,可以根据不同的请求方式去执行后台的不同方法
②restful风格的URL优点
结构清晰
符合标准
易于理解
扩展方便
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="param/testPathVariable/33">testPathVariable</a>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
public class ParamController {
/**
* @PathVariable注解
*/
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable(name = "id") String id){
System.out.println("正常运行");
System.out.println(id);
return "success";
}
}
注意:path = "/testPathVariable/{id}"中id和 @PathVariable(name=“id”)中id保持一致,且href=“anno/testPathVariable/10”,直接写入值,无需参数.
5.4 RequestHeader注解
1️⃣ 作用:获取指定请求头的值
2️⃣ 属性
value:请求头的名称
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="param/testRequestHeader">testRequestHeader</a>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
public class ParamController {
/**
* @RequestHeader注解
*/
@RequestMapping("/testRequestHeader")
public String testRequestHeader(@RequestHeader(value = "Accept") String header) {
System.out.println("正常运行");
System.out.println(header);
return "success";
}
}
5.5 CookieValue注解
1️⃣ 作用:用于获取指定cookie的名称的值
2️⃣ 属性
value:cookie的名称
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="param/testCookieValue">testCookieValue</a>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
public class ParamController {
/**
* @CookieValue注解
*/
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue(value = "JSESSIONID") String header) {
System.out.println("正常运行");
System.out.println(header);
return "success";
}
}
5.6 ModelAttribute注解
1️⃣ 作用
① 出现在方法上:表示当前方法会在控制器方法执行前先执行。
② 出现在参数上:获取指定的数据给参数赋值。
2️⃣ 应用场景
① 当提交表单数据不是完整的实体数据时,保证没有提交的字段使用数据库原来的数据。
5.6.1 出现在方法上
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="param/testModelAttribute" method="post">
用户姓名:<input type="text" name="uName"><br/>
用户年龄:<input type="text" name="uAge"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
public class ParamController {
/**
* @ModelAttribute注解
*/
@RequestMapping("/testModelAttribute")
public String testModelAttribute() {
System.out.println("testModelAttribute运行");
return "success";
}
@ModelAttribute
public void showUser(){
System.out.println("showUser方法执行了");
}
}
运行结果:
5.6.2 基于 Map 的应用场景示例:ModelAttribute 修饰方法带返回值
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="param/testModelAttribute" method="post">
用户姓名:<input type="text" name="uName"><br/>
用户年龄:<input type="text" name="uAge"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
public class ParamController {
/**
* @ModelAttribute注解
*/
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user) {
System.out.println("testModelAttribute运行");
System.out.println(user);
return "success";
}
/**
* 该方法会先执行
*/
@ModelAttribute
public User showUser(String uName){
System.out.println("showUser方法执行了");
// 通过用户查询数据库(模拟)
User user = new User();
user.setuName(uName);
user.setuAge(23);
user.setBirthDay(new Date());
return user;
}
}
结果:
5.6.3 基于 Map 的应用场景示例 :ModelAttribute 修饰方法不带返回值
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="param/testModelAttribute" method="post">
用户姓名:<input type="text" name="uName"><br/>
用户年龄:<input type="text" name="uAge"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.Map;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
@SessionAttributes()
public class ParamController {
/**
* @ModelAttribute注解
*/
@RequestMapping("/testModelAttribute")
public String testModelAttribute(@ModelAttribute("user") User user) {
System.out.println("testModelAttribute运行");
System.out.println(user);
return "success";
}
/**
* 该方法会先执行
*/
@ModelAttribute
public void showUser(String uName, Map<String, User> map){
System.out.println("showUser方法执行了");
// 通过用户查询数据库(模拟)
User user = new User();
user.setuName(uName);
user.setuAge(23);
user.setBirthDay(new Date());
map.put("user", user);
}
}
5.7 SessionAttributes注解
1️⃣ 作用:
用于多次执行控制器方法间的参数共享。
2️⃣ 属性:
value:用于指定存入的属性名称
type:用于指定存入的数据类型。
未加@SessionAttributes注解
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>入门成功</h3>
${requestScope.name}
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="param/testSessionAttributes">testSessionAttributes</a>
<br>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.Map;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
public class ParamController {
/**
* @SessionAttributes注解
*/
@RequestMapping("/testSessionAttributes")
public String testSessionAttributes(Model model) {
System.out.println("正常运行");
// 底层会存储到request域对象中
model.addAttribute("name", "zhangsan");
return "success";
}
}
@SessionAttributes注解
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>入门成功</h3>
${requestScope.name}
${sessionScope}
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.Map;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
@SessionAttributes(value = {"name"}) // 把name=zhangsan存入到session域中
public class ParamController {
/**
* @SessionAttributes注解
*/
@RequestMapping("/testSessionAttributes")
public String testSessionAttributes(Model model) {
System.out.println("正常运行");
// 底层会存储到request域对象中
model.addAttribute("name", "zhangsan");
return "success";
}
}
@SessionAttributes注解中实现获取和删除session域中对象
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>入门成功</h3>
${requestScope.name}
${sessionScope}
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="param/testSessionAttributes">testSessionAttributes</a>
<br>
<a href="param/getSessionAttributes">getSessionAttributes</a>
<br>
<a href="param/delSessionAttributes">delSessionAttributes</a>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.Account;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.Map;
/**
* @description: TODO 类描述
* @date: 2022/3/26 16:06
**/
@Controller
@RequestMapping("/param")
@SessionAttributes(value = {"name"}) // 把name=zhangsan存入到session域中
public class ParamController {
/**
* @SessionAttributes注解
*/
@RequestMapping("/testSessionAttributes")
public String testSessionAttributes(Model model) {
System.out.println("正常运行");
// 底层会存储到request域对象中
model.addAttribute("name", "zhangsan");
return "success";
}
/**
* Session域获取值
* @param modelMap
* @return
*/
@RequestMapping(path = "/getSessionAttributes")
public String getSessionAttributes(ModelMap modelMap){
System.out.println("getSessionAttributes....");
String msg = (String)modelMap.get("name");
System.out.println(msg);
return "success";
}
/**
* Session域清除
* @param status
* @return
*/
@RequestMapping(path = "/delSessionAttributes")
public String delSessionAttributes(SessionStatus status){
System.out.println("delSessionAttributes....");
status.setComplete();
return "success";
}
}
6 响应数据和结果视图
6.1 返回值分类
6.1.1 返回字符串
Controller方法返回字符串可以指定逻辑视图的名称,根据视图解析器解析为物理视图的地址。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="returnValue/testString">testString</a>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>入门成功</h3>
${user.uName}
${user.birthDay}
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Date;
/**
* @description: TODO 类描述
* @date: 2022/3/26 21:00
**/
@Controller
@RequestMapping("/returnValue")
public class ReturnValueController {
@RequestMapping("/testString")
public String testString(Model model){
System.out.println("testString方法执行了");
// 模拟从数据库中查询user对象
User user = new User();
user.setuName("haha");
user.setuAge(23);
user.setBirthDay(new Date());
// 底层会存储到request域对象中
model.addAttribute("user", user);
return "success";
}
}
6.1.2 返回值是void
① 如果控制器的方法返回值编写成void,执行程序报404的异常,默认查找JSP页面没有找到。
默认会跳转到@RequestMapping(value="/initUpdate") initUpdate的页面。
② 可以使用请求转发或者重定向跳转到指定的页面
请求转发、重定向和直接响应
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="returnValue/testVoid">testVoid</a>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>请求转发</h3>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Date;
/**
* @description: TODO 类描述
* @date: 2022/3/26 21:00
**/
@Controller
@RequestMapping("/returnValue")
public class ReturnValueController {
/**
* 请求转发
*/
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("testVoid方法执行了");
// 1. 请求转发
//request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response);
// 2. 重定向
//response.sendRedirect(request.getContextPath() + "/response.jsp");
// 设置中文乱码
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 3. 直接会进行响应
response.getWriter().print("你好");
return;
}
}
6.1.3 返回值是ModelAndView对象
ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="returnValue/testModelAndView">testModelAndView</a>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.User;
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.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* @description: TODO 类描述
* @date: 2022/3/26 21:00
**/
@Controller
@RequestMapping("/returnValue")
public class ReturnValueController {
/**
* 返回值是 ModelAndView
*/
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
System.out.println("testModelAndView方法执行了");
// 创建ModelAndView对象
ModelAndView modelAndView = new ModelAndView();
// 模拟从数据库中查询User对象
User user = new User();
user.setuName("haha");
user.setuAge(23);
user.setBirthDay(new Date());
// 把user对象存储到mv对象中,也会把user对象存入到request对象
modelAndView.addObject("user", user);
// 跳转到哪个页面
modelAndView.setViewName("success");
return modelAndView;
}
}
6.2 SpringMVC框架提供的转发和重定向
6.2.1 forward请求转发
controller 方法在提供了 String 类型的返回值之后,默认就是请求转发。也可以写成如下方式:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="returnValue/testForward">testForward</a>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.User;
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.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* @description: TODO 类描述
* @date: 2022/3/26 21:00
**/
@Controller
@RequestMapping("/returnValue")
public class ReturnValueController {
@RequestMapping("/testForward")
public String testForward(){
System.out.println("testForward方法执行了");
// 请求转发
return "forward:/WEB-INF/pages/success.jsp";
}
}
6.2.2 redirect重定向
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="returnValue/testRedirect">testRedirect</a>
</body>
</html>
package com.pikaqiu.controller;
import com.pikaqiu.domain.User;
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.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* @description: TODO 类描述
* @date: 2022/3/26 21:00
**/
@Controller
@RequestMapping("/returnValue")
public class ReturnValueController {
@RequestMapping("/testRedirect")
public String testRedirect(){
System.out.println("testRedirect方法执行了");
// 重定向
return "redirect:/response.jsp";
}
}
6.3 ResponseBody响应json数据
DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置
- mvc:resources标签配置不过滤
- location元素表示webapp目录下的包下的所有文件
- mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解扫描-->
<context:component-scan base-package="com.pikaqiu"></context:component-scan>
<!--视图解析器-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--配置自定义类型转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.pikaqiu.util.StringToDateConverter"></bean>
</set>
</property>
</bean>
<!--前端控制器,哪些静态资源不拦截-->
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/images/**" location="/images/"/>
<mvc:resources mapping="/js/**" location="/js/" />
<!--开启SpringMVC框架注解的支持-->
<!--会自动注册RequestMappingHandlerMapping与RequestMappingHandlerAdapter两个Bean-->
<mvc:annotation-driven conversion-service="conversionService"/>
</beans>
@RequestBody注解用于将 Controller 的方法返回的对象,通过 HttpMessageConverter 接口转换为指定格式的数据如:json,xml 等,通过 Response 响应给客户端。
- 使用@RequestBody获取请求体数据
- 使用@RequestBody注解把json的字符串转换成JavaBean的对象
- 使用@ResponseBody注解把JavaBean对象转换成json字符串,直接响应
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="js/jquery.min.js"></script>
<script>
//页面加载,绑定单击事件
$(function () {
$("#btn").click(function(){
// alert("hello btn");
// 发送ajax请求
$.ajax({
// 编写json格式,设置属性和值
url:"user/testAjax",
contentType:"application/json;charset=UTF-8",
data:'{"username":"hehe", "password":"123", "age":"30"}',
dataType:"json",
type:"post",
success:function (data) {
// data服务器端响应的json的数据,进行解析
alert(data);
alert(data.username);
alert(data.password);
}
})
});
});
</script>
</head>
<body>
<button id="btn">发送ajax的请求</button>
</body>
</html>
json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包
<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-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
package com.pikaqiu.controller;
import com.pikaqiu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* @description: TODO 类描述
* @date: 2022/3/26 21:00
**/
@Controller
@RequestMapping("/returnValue")
public class ReturnValueController {
/**
* 模拟异步请求响应
*/
public @ResponseBody User testAjax(@RequestBody User user){
System.out.println("testAjax方法执行了");
// 客户端发送ajax请求,传的是json字符串,后端把json字符串封装到user对象中
System.out.println(user);
// 做响应后,模拟查询数据库
user.setuName("lisi");
user.setuAge(66);
// 作响应,@ResponseBody会将user对象转成json格式
return user;
}
}
7 SpringMVC实现文件上传
7.1 文件上传的必要前提
-
form 表单的 enctype 取值必须是:multipart/form-data
(默认值是:application/x-www-form-urlencoded) enctype:是表单请求正文的类型
-
method 属性取值必须是 Post
-
提供一个文件选择域
7.2 传统文件上传方法
导入文件的jar包
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>文件上传</h3>
<form action="user/testFileUpload" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload" /><br/>
<input type="submit" value="上传"/>
</form>
</body>
</html>
package com.pikaqiu.controller;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.List;
import java.util.UUID;
/**
* @description: TODO 类描述
* @date: 2022/3/27 16:21
**/
@Controller
@RequestMapping("/file")
public class FileUploadController {
@RequestMapping("/testFileUpload")
public String testFileUpload(HttpServletRequest request) throws Exception {
System.out.println("文件上传");
// 使用功能fileupload组件完成文件上传
// 上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
File file = new File(path);
if(!file.exists()){
// 创建该文件夹
file.mkdirs();
}
// 实现步骤
// 1、创建DiskFileItemFactory对象,设置缓冲区大小和临时文件目录
// 2、使用DiskFileItemFactory 对象创建ServletFileUpload对象,并设置上传文件的大小限制。
// 3、调用ServletFileUpload.parseRequest方法解析request对象,得到一个保存了所有上传内容的List对象。
// 4、对list进行迭代,每迭代一个FileItem对象,调用其isFormField方法判断是否是上传文件
// True 为普通表单字段,则调用getFieldName、getString方法得到字段名和字段值
// False 为上传文件
// 解析request对象,获取上传文件项
DiskFileItemFactory factory = new DiskFileItemFactory();
// 创建一个上传工具,指定使用缓存区与临时文件存储位置
ServletFileUpload upload = new ServletFileUpload(factory);
// 解析request
// 它是用于解析request对象,得到所有上传项.每一个FileItem就相当于一个上传项
List<FileItem> fileItems = upload.parseRequest(request);
// 遍历
for(FileItem item:fileItems){
// 进行判断,当前item是否是上传文件对象
if(item.isFormField()){
// true,说明是普通表单相
}else{
// 说明是上传文件项
// 获取上传文件的名称
String filename = item.getName();
// 把文件的名称设置为唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid + "_" + filename;
// 完成文件上传
item.write(new File(path, filename));
item.delete();
}
}
return "success";
}
}
7.3 SpringMVC传统方式文件上传
SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件,要求变量名称必须和表单file标签的 name属性名称相同。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>文件上传</h3>
<form action="file/testFileUploadBySpringMVC" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"><br/>
<input type="submit" value="上传">
</form>
</body>
</html>
springmvc.xml中配置文件解析器对象
<!-- 配置文件解析器对象,要求id名称必须是multipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10485760"/>
</bean>
注意:id名称必须是multipartResolver, 选择文件: 和 MultipartFile upload中的 upload 保持一致
package com.pikaqiu.controller;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
/**
* @description: TODO 类描述
* @date: 2022/3/27 16:21
**/
@Controller
@RequestMapping("/file")
public class FileUploadController {
/**
* SpringMVC文件上传
*/
@RequestMapping("/testFileUploadBySpringMVC")
public String testFileUploadBySpringMVC(HttpServletRequest request, MultipartFile upload) throws Exception {
System.out.println("springMVC文件上传");
// 使用功能fileupload组件完成文件上传
// 上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
// System.out.println(path);
// 判断,该路径是否存在
File file = new File(path);
if(!file.exists()){
// 创建该文件夹
file.mkdirs();
}
// 获取到上传文件的名称
String fileName = upload.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replace("-", "");
// 把文件的名称唯一化
fileName = uuid + "-" + fileName;
// 完成文件上传
upload.transferTo(new File(path, fileName));
return "success";
}
}
7.4 SpringMVC跨服务器方式文件上传
导入开发需要的jar包
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.18.1</version>
</dependency>
参考: