Spring MVC的请求和响应
一、SpringMVC请求与响应的基本理论
在Web应用中,请求与响应是前端与后端之间的主要交互方式。具体到Spring MVC框架,请求通常指客户端发送到服务器的HTTP请求,而响应指服务器对请求的反馈。
请求与响应的处理流程
- HTTP请求:客户端(如浏览器)发送请求(包括请求路径、方法、参数等),Spring MVC通过DispatcherServlet接收到请求,进行处理。
- 控制器(Controller):根据请求的不同,DispatcherServlet会将请求分派到相应的控制器方法,进行逻辑处理。
- 视图解析(View Resolver):控制器返回的视图名称将通过视图解析器转换为具体的视图(如JSP页面、Thymeleaf模板等)。
- HTTP响应:控制器返回的数据可以通过视图渲染成HTML,也可以直接以JSON或XML格式返回给客户端。
Spring MVC 请求-响应流程图
二、RequestMapping注解
RequestMapping注解的作用是建立请求URL和处理方法之间的对应关系
RequestMapping注解可以作用在方法和类上
1. 作用在类上:第一级的访问目录
2. 作用在方法上:第二级的访问目录
3. 细节:路径可以不编写 / 表示应用的根目录开始
1、RequestMapping的属性
import org.springframework.stereotype.Controller;
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;
@Controller
@RequestMapping("/Hello")// 路径不能一样
public class HelloController {
// 返回页面
// 最常用的方式
@RequestMapping("/toA")
public String toA(){
return "A";
}
// jsp的形式
// 还没被淘汰,使用比较少
@RequestMapping("/toB")
public ModelAndView toB(){
ModelAndView mv =new ModelAndView();
mv.addObject("msg","this is msg B");
mv.setViewName("B");
return mv;
}
@RequestMapping("/test")
public void test(HttpServletRequest request,HttpServletResponse response) throws IOException {
response.getWriter().println("hello ,String");
}
}
2、常用的 RequestMaping 属性
属性 | 说明 | 示例 |
value | 映射的URL路径 | @RequestMapping("/greet") |
method | 指定请求方法类型(GET, POST等) | @RequestMapping(method = RequestMethod.GET) |
params | 请求参数的条件 | @RequestMapping(params = "id=1") |
headers | 请求头的条件 | @RequestMapping(headers = "key=value") |
produces | 指定返回的内容类型(MIME类型) | @RequestMapping(produces = "application/json") |
consumes | 指定请求的内容类型 | @RequestMapping(consumes = "application/json") |
3、请求参数绑定
public String save3(@RequestParam(value = "name",required = false)String name){
System.out.println(name);
return "B";
}
三、转发和重定向
1、转发和重定向
Spring MVC支持两种类型的跳转:
- 转发(forward):服务器端的请求转发,页面仍然保持在当前地址。
- 重定向(redirect):客户端的请求重新发送,浏览器地址栏会发生变化。
// 请求转发————》只能在网站内部资源之间进行转发
/*
* 请求转发本身是一种服务器端行为
* 浏览器的地址栏不会发生任何变化
* 从始至终都是一个请求
* request信息在Servlet中是共享的,因为从始至终都是一个request
* */
// 将test1中的request信息转发的test2中
@RequestMapping("/test1")
public void test1(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {
request.getRequestDispatcher("test2").forward(request,response);
}
@RequestMapping("/test2")
public void test2(HttpServletRequest request,HttpServletResponse response) throws IOException {
String name = request.getParameter("name");
String password = request.getParameter("password");
System.out.println(name+ " "+ password);
}
// 重定向————》 可以访问站外资源
/*
* 本身是一种客户端行为
* 地址栏发生改变
* 浏览器会发起两次请求
*
* */
@RequestMapping("/test3")
public void test3(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {
response.sendRedirect("/SpringMVC_Demo/Hello/test4");
}
@RequestMapping("/test4")
public void test4(HttpServletRequest request,HttpServletResponse response) throws IOException {
System.out.println("this msg ordered from test3");
}
// @RequestMapping("/t1")
// public String testt(){
// return "B";
// }
/*
* SprintMVC 的请求和转发,不会走配置的页面路径
* */
@RequestMapping("/t1")
public String testt(){
return "forward:/html/B.html";
}
@RequestMapping("/t2")
public String testt2(){
return "redirect:/html/B.html";
}
2、返回JSON相应
Spring MVC支持自动将Java对象转化为JSON格式并返回。只需要在方法上使用
@ResponseBody 注解即可。
import com.goose.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/B")
public class BController {
@RequestMapping("/find")
@ResponseBody // 保证返回的数据是json格式
public User find(){
User user =new User("张三",12,'女');
return user;
}
}
四、实现文件上传和下载
1、文件上传
/**
* 文件上传功能
* @param file
* @return
* @throws IOException
*/
@RequestMapping(value="/upload",method= RequestMethod.POST)
@ResponseBody
public String upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {
// uploads文件夹位置
String rootPath = request.getSession().getServletContext().getRealPath("WEB-INF/upload");
// 原始名称
String originalFileName = file.getOriginalFilename();
// 新文件
File newFile = new File(rootPath + File.separator + File.separator + originalFileName);
// 判断目标文件所在目录是否存在
if( !newFile.getParentFile().exists()) {
// 如果目标文件所在的目录不存在,则创建父目录
newFile.getParentFile().mkdirs();
}
System.out.println("----------");
System.out.println("----------");
System.out.println("----------");
System.out.println("----------");
System.out.println("----------");
System.out.println("----------");
System.out.println("----------");
System.out.println(newFile);
// 将内存中的数据写入磁盘
file.transferTo(newFile);
return "{\"data\":\"success\"}";
}
文件上传常见问题
问题 | 解决方案 |
文件过大 | 在 CommonsMultipartResolver 中设置 maxUploadSize |
文件名冲突 | 可通过自定义文件名生成逻辑解决(如加时间戳) |
文件类型限制 | 可以通过 Content-Type 进行限制 |
2、文件下载(本地文件目录模拟数据库)
/**
* 文件下载功能
* @param request
* @param response
* @throws Exception
*/
@RequestMapping("/down")
public void down(HttpServletRequest request, HttpServletResponse response) throws Exception{
String filename = request.getParameter("filename");
System.out.println(filename);
//模拟文件,myfile.txt为需要下载的文件
String fileName = request.getSession().getServletContext().getRealPath("WEB-INF/upload")+"/"+filename;
//获取输入流
InputStream bis = new BufferedInputStream(new FileInputStream(new File(fileName)));
//假如以中文名下载的话
// String filename = "下载文件.txt";
//转码,免得文件名中文乱码
filename = URLEncoder.encode(filename,"UTF-8");
//设置文件下载头
response.addHeader("Content-Disposition", "attachment;filename=" + filename);
//1.设置文件ContentType类型,这样设置,会自动判断下载文件类型
response.setContentType("multipart/form-data");
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
int len = 0;
while((len = bis.read()) != -1){
out.write(len);
out.flush();
}
out.close();
}
五、需要的配置文件
1、pom.xml
<?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.goose</groupId>
<artifactId>SpringMVC_Demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>SpringMVC_Demo 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>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<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>
<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>
<!--SpringMVC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!--servlet API-->
<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>
<!--日志-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-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>
<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>
</dependencies>
<build>
<finalName>SpringMVC_Demo</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.4.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.3.1</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.3.0</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.4.0</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>3.1.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.1.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
2、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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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">
<!--配置spring创建容器时要扫描的包-->
<context:component-scan base-package="com.goose"></context:component-scan>
<!--设置静态资源不过滤-->
<mvc:resources mapping="/css/**" location="/css/"/> <!--样式-->
<mvc:resources mapping="/images/**" location="/images/"/> <!--图片-->
<mvc:resources mapping="/js/**" location="/js/"/> <!--javascript-->
<!--配置文件上传的解析器组件。id的名称是固定,不能乱写-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置上传文件的总大小 8M = 8 * 1024 * 1024 -->
<property name="maxUploadSize" value="8388608" />
</bean>
<!--处理映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--配置视图解析器-->
<bean id="viewResolver" class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine" ref="templateEngine"/>
</bean>
<!-- templateEngine -->
<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver"/>
</bean>
<bean id="templateResolver" class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/html/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5"/>
</bean>
<!-- JSON View -->
<bean
class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
</bean>
<!-- 配置spring开启注解mvc的支持 默认就是开启的 ,要想让其他组件(不包含映射器、适配器、处理器)生效就必须需要配置了-->
<mvc:annotation-driven/>
</beans>
3、web.xml
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<!--在web.xml中配置Spring提供的过滤器类 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<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>
<!--不拦截所有是html的页面请求-->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<!--配置前端控制器,对浏览器发送的请求进行统一处理-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--加载springmvc.xml配置文件的位置和名称,配置的是Spring配置-->
<init-param>
<!--contextConfigLocation:上下文配置路径,固定值-->
<param-name>contextConfigLocation</param-name>
<!--classpath:类路径,值得是Java和resources文件夹-->
<!--springmvc.xml:指的是配置文件的名称:需要配置springmvc.xml,在下面-->
<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>
<!--开启项目时打开的页面-->
<welcome-file-list>
<welcome-file>/index.html</welcome-file>
</welcome-file-list>
</web-app>
4、file.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>this page for file updown and shangchuan</title>
</head>
<body>
<h1>文件上传</h1>
<form action="/SpringMVC_Demo/file/upload" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="file" width="120px">
<input type="submit" value="上传">
</form>
<div id="upMenu" class="white_content">
<form id="downForm" lay-filter="updata" action="/SpringMvc_Demo/file/down" method="get">
请输入想要下载的文件名称:<input type="text" id="filename" name="filename">
<input type="submit" value="下载">
</form>
<input type="button" value="完成"/>
</div>
</body>
</html>