Spring MVC 基础 MVC设计模式 MVC是Model-View-Controller的缩写,是一种经典的软件设计模式,用于组织和管理应用程序的代码结构。
模型(Model) :模型代表应用程序的数据和业务逻辑。它负责处理数据以及与数据库、文件系统等进行交互,并提供对外的接口供控制器使用。模型通常会封装数据的读取、写入、更新和删除操作。视图(View) :视图是用户界面的呈现层,负责展示模型中的数据给用户。它通常是用户可以看到和与之交互的部分,如网页、窗口、按钮等。视图可以直接从模型获取数据,但不能修改数据,只能通过控制器来间接操作模型。控制器(Controller) :控制器充当模型和视图之间的协调者,处理用户的输入和交互。它接收用户的请求并根据请求调用合适的模型方法来处理数据操作,最后将结果传递给视图进行展示。控制器还负责将模型和视图解耦,确保它们之间的独立性。Spring MVC简介 Spring MVC 是 Spring 框架的一个模块,是基于 MVC 设计模式的轻量级、灵活且功能强大的框架,用于构建可扩展和高效的 Web 应用
Spring MVC 核心组件 前端控制器(DispatcherServlet) :统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求处理器映射器(HandlerMapping) :根据请求的url、method等信息查找Handler(控制器方法)处理器适配器(HandlerAdapter) :通过HandlerAdapter对处理器(控制器方法)进行执行处理器(Handler) :在DispatcherServlet的控制下Handler对具体的用户请求进行处理,通俗讲就是Controller层所写的业务代码视图解析器(ViewResolver) :进行视图解析,得到相应的视图,如 JSP、Thymeleaf 或 FreeMarker 等视图(View) :用于表示视图,可以是JSP、Thymeleaf 或 FreeMarker 等各种模板技术。Spring MVC 执行流程 SpringMVC底层是Servlet,以Servlet为核心来接收请求,处理请求,显示处理结果给用户
客户端发送请求 :客户端(浏览器)发送请求到服务器;前端控制器拦截请求 :Servlet 容器会将请求交给 Spring 的 前端控制器(DispatcherServlet),进行拦截请求,并委托给处理器映射器(HandlerMapping)进行处理处理器映射器处理请求 :处理器映射器(HandlerMapping)根据请求 URL 找到对应的 处理器(Controller)或 处理器链(HandlerExecutionChain)返回给 前端控制器(DispatcherServlet)处理器适配器处理请求 :前端控制器(DispatcherServlet)将找到的处理器(Controller)或 处理器链(HandlerExecutionChain)交给处理器适配器(HandlerAdapter)去调用合适的处理器(Controller)处理器处理请求 :处理器(Controller)执行业务逻辑,处理请求并生成模型数据,然后返回一个逻辑视图名(Logical View Name)或 ModelAndView 对象,返回给前端控制器(DispatcherServlet);视图解析器解析视图 :前端控制器(DispatcherServlet)将逻辑视图名或 ModelAndView 对象传递给视图解析器(ViewResolver),视图解析器根据逻辑视图名解析出一个具体的视图对象(如 JSP、Thymeleaf 或 FreeMarker 等)并响应给前端控制器(DispatcherServlet)渲染视图并响应 :前端控制器(DispatcherServlet)调用视图对象(View)的渲染方法,将模型数据填充到视图中,并生成最终的响应结果,将其返回给客户端(浏览器)。Spring MVC 入门案例 添加SpringMVC依赖 创建Maven工程,在pom文件中指定打包方式,添加依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <packaging > war</packaging > <dependencies > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-webmvc</artifactId > <version > 5.3.1</version > </dependency > <dependency > <groupId > ch.qos.logback</groupId > <artifactId > logback-classic</artifactId > <version > 1.2.3</version > </dependency > <dependency > <groupId > javax.servlet</groupId > <artifactId > javax.servlet-api</artifactId > <version > 3.1.0</version > <scope > provided</scope > </dependency > <dependency > <groupId > org.thymeleaf</groupId > <artifactId > thymeleaf-spring5</artifactId > <version > 3.0.12.RELEASE</version > </dependency > </dependencies >
Controller控制层 创建Controller包,包下创建HelloController类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Controller @RequestMapping("/springMVC") public class HelloController { @RequestMapping("/") public String index () { System.out.println("访问首页成功" ); return "index" ; } }
注册SpringMVC的前端控制器 修改src/main/webapp/WEB-INF/web.xml,注册SpringMVC的前端控制器DispatcherServlet(默认配置方式)此配置作用下,SpringMVC的配置文件默认位于WEB-INF下,默认名称为- servlet.xml,例如,以下配置所对应SpringMVC的配置文件位于WEB-INF下,文件名为springMVCservlet.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 <?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" > <servlet > <servlet-name > springMVC</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > <init-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:springMVC-servlet.xml</param-value > </init-param > <load-on-startup > 1</load-on-startup > </servlet > <servlet-mapping > <servlet-name > springMVC</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping > </web-app >
SpringMVC的配置文件 创建SpringMVC的配置文件,配置文件名称为web.xml文件中<servlet-name>标签中的名称-servlet.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?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 ="Controller" /> <bean id ="viewResolver" class ="org.thymeleaf.spring5.view.ThymeleafViewResolver" > <property name ="order" value ="1" /> <property name ="characterEncoding" value ="UTF-8" /> <property name ="templateEngine" > <bean class ="org.thymeleaf.spring5.SpringTemplateEngine" > <property name ="templateResolver" > <bean class ="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver" > <property name ="prefix" value ="/WEB-INF/templates/" /> <property name ="suffix" value =".html" /> <property name ="templateMode" value ="HTML5" /> <property name ="characterEncoding" value ="UTF-8" /> </bean > </property > </bean > </property > </bean > </beans >
创建index.html页面 在/WEB-INF/templates/下创建index.html页面
1 2 3 4 5 6 7 8 9 10 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <p > Hello!Controller!</p > ></body > </html >
启动Tomcat 配置并启动Tomcat,访问localhost:8080/springMVC/后,页面显示Hello!Controller!,控制台打印访问首页成功
请求与响应的处理 请求方法的处理 使用@RequestMapping注解 @RequestMapping注解是Spring MVC框架中的一个注解,用于映射URL和方法之间的关系,可以应用于控制器类或方法上,同时可以接受多个参数实现更精确的请求映射,如下
value :指定映射的URL路径method :指定处理请求的HTTP方法params :指定请求中必须包含的参数及其值headers :指定请求中必须包含的头部信息consumes :指定请求的Content-Type(请求的媒体类型)produces :指定响应的Content-Type(返回的媒体类型)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 @Controller @RequestMapping("/") public class TestController { @RequestMapping(value = "/test1") public void hello1 () { } @RequestMapping(value = {"/test2", "/test3"}) public void hello2 () { } @RequestMapping(value = "/test4", method = RequestMethod.GET) public void hello3 () { } @RequestMapping(value = "/test5", method = {RequestMethod.GET, RequestMethod.POST}) public void hello4 () { } @RequestMapping(value = "/test6", method = RequestMethod.GET, params = {"username", "!password", "username=wen", "gender!=女"} ) public void hello5 () { } @RequestMapping(value = "/test7", method = RequestMethod.GET, headers = {"username", "!password", "username=wen", "gender!=女"}) public void hello6 () { } @RequestMapping(value = "/test8", method = RequestMethod.POST, consumes = "application/json") public void hello7 () { } @RequestMapping(value = "/test9", method = RequestMethod.GET, produces = "application/json") @ResponseBody public Map<String, Object> hello8 () { Map<String, Object> result = new HashMap <String, Object>(); result.put("message" , "Hello, World!" ); return result; } }
使用@RequestMapping衍生注解 @RequestMapping为了让开发人员能够更直观地定义处理不同HTTP请求方法的方法,还提供了一些衍生注解:
@GetMapping:用于处理HTTP GET请求。等同于@RequestMapping(method = RequestMethod.GET)。@PostMapping:用于处理HTTP POST请求。等同于@RequestMapping(method = RequestMethod.POST)。@PutMapping:用于处理HTTP PUT请求。等同于@RequestMapping(method = RequestMethod.PUT)。@DeleteMapping:用于处理HTTP DELETE请求。等同于@RequestMapping(method = RequestMethod.DELETE)。@PatchMapping:用于处理HTTP PATCH请求。等同于@RequestMapping(method = RequestMethod.PATCH)。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 @Controller public class TestController { @GetMapping("/get") public void testGet () { } @PostMapping("/post") public void testPost () { } @PutMapping("/put") public void testPut () { } @DeleteMapping("/delete") public void testDelete () { } @PatchMapping("/patch") public void testPatch () { } }
路径参数的处理 RESTful风格简介 Restful风格指的是网络应用中就是资源定位和资源操作的风格,将HTTP 协议里四个表示操作方式的动词GET、POST、PUT、DELETE,分别对应四种基本操作
请求 对应操作 简介 GET 查询 用来获取资源 POST 新增 用来新建资源 PUT 修改 用来更新资源 DELETE 删除 用来删除资源
REST 风格提倡 URL 地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方式携带请求参数,而是将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性
请求方式 传统风格 REST风格 对应操作 GET getUserById user 查询所有信息 GET getUserById?id=1 user/1 查询指定信息 POST saveUser user 添加信息 DELETE deleteUser?id=1 user/1 删除信息 PUT updateUser user 修改更新信息
路径参数简介 路径参数是指URL中的一部分被用作参数的部分,可以使用占位符{parameter}来标识,比如/users/{id}中的{id}就是一个路径参数。在使用RESTful风格设计API时,一般会通过路径参数来表示资源的唯一标识、层级关系或传递参数信息
使用@PathVariable注解 @PathVariable注解用于获取URL路径中的参数,路径参数是指URL中的一部分被用作参数的部分,可以使用占位符{parameter}来标识,并在方法参数上使用@PathVariable注解来获取参数值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Controller public class TestController { @GetMapping("/user/{id}") public void getUserById (@PathVariable("id") String id) { System.out.println(id); } }
请求参数的处理 使用HttpServletRequest对象 HttpServletRequest对象是Servlet规范中定义的接口,它提供了丰富的方法来访问HTTP请求的信息,包括请求参数、请求头、请求方法等。通过HttpServletRequest对象,我们可以获取请求参数的值,并进行相应的处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 @Controller public class TestController { @GetMapping("/getParameter") public void getParameter (HttpServletRequest request) { String username = request.getParameter("username" ); String password = request.getParameter("password" ); System.out.println("username:" + username); System.out.println("password:" + password); } @GetMapping("/getParameterValues") public void getParameterValues (HttpServletRequest request) { String[] parameterValues = request.getParameterValues("parameterName" ); if (parameterValues != null ) { for (String value : parameterValues) { System.out.println("value:" + value); } } } @GetMapping("/getParameterMap") public void getParameterMap (HttpServletRequest request) { Map<String, String[]> parameterMap = request.getParameterMap(); for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) { String parameterName = entry.getKey(); String[] parameterValues = entry.getValue(); System.out.println("parameterName:" + parameterName); for (String value : parameterValues) { System.out.println("value:" + value); } } } }
使用@RequestParam注解 @RequestParam注解用于获取请求参数或请求体参数。可以应用在方法的参数上,用于指定要获取的参数名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Controller public class TestController { @GetMapping("/getUserName") public void getUserName (@RequestParam(value = "param", required = false, defaultValue = "wen") String param) { System.out.println("请求参数内容:" + param); } }
请求体的处理 使用HttpServletRequest对象 HttpServletRequest对象是Servlet规范中定义的接口,它提供了丰富的方法来访问HTTP请求的信息,包括请求参数、请求头、请求方法等。通过HttpServletRequest对象,我们可以获取请求参数的值,并进行相应的处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 @Controller public class TestController { @GetMapping("/getInputStream") public void getInputStream (HttpServletRequest request) { try { InputStream inputStream = request.getInputStream(); byte [] buffer = new byte [1024 ]; int length; StringBuilder requestBody = new StringBuilder (); while ((length = inputStream.read(buffer)) != -1 ) { requestBody.append(new String (buffer, 0 , length)); } inputStream.close(); System.out.println("请求体内容:" + requestBody.toString()); } catch (IOException e) { e.printStackTrace(); } } @GetMapping("/getReader") public void getReader (HttpServletRequest request) { try { BufferedReader reader = request.getReader(); StringBuilder requestBody = new StringBuilder (); String line; while ((line = reader.readLine()) != null ) { requestBody.append(line); } reader.close(); System.out.println("请求体内容:" + requestBody.toString()); } catch (IOException e) { e.printStackTrace(); } } }
使用@RequestParam注解 @RequestParam注解用于获取请求参数或请求体参数。可以应用在方法的参数上,用于指定要获取的参数名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Controller public class TestController { @GetMapping("/getUserName") public void getUserName (@RequestParam(value = "requestBody", required = false, defaultValue = "wen") String requestBody) { System.out.println("请求体参数内容:" + requestBody); } }
使用@RequestBody注解 @RequestBody注解用于将HTTP请求的内容绑定到方法的参数上,通常用于接收请求体中的JSON或XML数据,并将其转换为对象。它可以应用在方法的参数上,指示要绑定的请求体参数类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 @Controller public class TestController { @PostMapping("/listJsonData") public void listJsonData (@RequestBody List<String> listJson) { System.out.println("listJson = " + listJson); } @PostMapping("/mapJsonData") public void mapJsonData (@RequestBody Map<String, Object> mapJson) { System.out.println("mapJson = " + mapJson); } @PostMapping("/userJsonData") public void userJsonData (@RequestBody User userJson) { System.out.println("userJson = " + userJson); } @PostMapping("/userArrayJsonData") public void userArrayJsonData (@RequestBody User[] userArrayJson) { System.out.println("userArrayJson = " + Arrays.toString(userArrayJson)); } @PostMapping("/userListJsonData") public void userListJsonData (@RequestBody List<User> userListJson) { System.out.println("userListJson = " + userListJson); } @PostMapping("/textData") public void textData (@RequestBody String requestBody) { System.out.println("请求体内容:" + requestBody); } @PostMapping("/xmlData") public void xmlData (@RequestBody String requestBody) { System.out.println("请求体内容:" + requestBody); } @PostMapping("/binaryData") public void binaryData (@RequestBody byte [] requestBody) { System.out.println("请求体内容长度:" + requestBody.length); } @PostMapping("/fileData") public void fileData (@RequestParam("file") MultipartFile file) { if (!file.isEmpty()) { try { byte [] fileBytes = file.getBytes(); System.out.println("文件名称:" + file.getOriginalFilename()); System.out.println("文件大小:" + file.getSize() + " bytes" ); } catch (IOException e) { e.printStackTrace(); } } } }
请求头的处理 使用HttpServletRequest对象 HttpServletRequest对象是Servlet规范中定义的接口,它提供了丰富的方法来访问HTTP请求的信息,包括请求参数、请求头、请求方法等。通过HttpServletRequest对象,我们可以获取请求参数的值,并进行相应的处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Controller public class TestController { @GetMapping("/getParameter") public void getParameter (HttpServletRequest request) { String userAgent = request.getHeader("User-Agent" ); System.out.println(userAgent); } }
@RequestHeader注解用于从请求头中获取参数值。可以应用在方法的参数上,指定要获取的参数名称,并将对应的值作为方法参数进行处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Controller public class TestController { @GetMapping("/getUserAgent") public void getUserAgent (@RequestHeader("User-Agent") String userAgent) { System.out.println(userAgent); } }
Cookie的处理 使用HttpServletRequest对象 HttpServletRequest对象是Servlet规范中定义的接口,它提供了丰富的方法来访问HTTP请求的信息,包括请求参数、请求头、请求方法等。通过HttpServletRequest对象,我们可以获取请求参数的值,并进行相应的处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Controller public class TestController { @GetMapping("/hello") public void sayHello (HttpServletRequest request) { Cookie[] cookies = request.getCookies(); if (cookies != null ) { for (Cookie cookie : cookies) { String name = cookie.getName(); String value = cookie.getValue(); System.out.println("Cookie Name: " + name); System.out.println("Cookie Value: " + value); } } else { System.out.println("No cookies found in the request" ); } } }
使用@CookieValue注解 @CookieValue注解用于从请求的Cookie中获取参数值。可以应用在方法的参数上,指定要获取的Cookie名称,并将对应的值作为方法参数进行处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Controller public class TestController { @GetMapping("/getCookieValue") public void getCookieValue (@CookieValue("sessionId") String sessionId) { System.out.println(sessionId); } }
响应的处理 响应视图 当控制器方法返回一个视图名称时,Spring MVC会根据配置的视图解析器来解析该视图名称,并找到相应的视图模板文件。然后,框架将模型中的数据填充到模板中,生成最终的响应内容,并将其返回给客户端。
1 2 3 4 5 6 7 8 9 @Controller public class TestController { @GetMapping("/index") public String home () { return "index" ; } }
响应转发 当控制器方法返回一个请求转发路径时,Spring MVC会将请求转发到指定的路径。这样可以实现在服务器内部跳转,不改变客户端的URL。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Controller public class TestController { @GetMapping("/forward") public String forward () { return "forward:/www.baidu.com" ; } }
响应重定向 当控制器方法返回一个重定向路径时,Spring MVC会将请求重定向到指定的路径。这样可以实现在客户端进行URL跳转。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Controller public class TestController { @GetMapping("/redirect") public String redirect () { return "redirect:/www.baidu.com" ; } }
响应JSON数据 当控制器方法需要返回JSON数据时,可以在方法中使用 @ResponseBody 注解来指定返回的数据会以JSON格式进行序列化,并直接返回给客户端。注意:每个方法只能使用一次@ResponseBody注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 @Controller public class TestController { @ResponseBody @GetMapping("/listJson") public List<String> getListJson () { ArrayList<String> listJson = new ArrayList <>(); listJson.add("My first json" ); listJson.add("My second json" ); listJson.add("My third json" ); return listJson; } @ResponseBody @GetMapping("/mapJson") public Map<String, Object> getMapJson () { Map<String, Object> mapJson = new HashMap <String, Object>(); mapJson.put("name" , "John" ); mapJson.put("age" , 25 ); return mapJson; } @ResponseBody @RequestMapping("/userJson") public User getUserJson () { return new User (1 , "小明" , "123456" ); } }
响应XML数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Controller public class TestController { @GetMapping(value = "/xml", produces = MediaType.APPLICATION_XML_VALUE) public Map<String, Object> getXmlData () { Map<String, Object> data = new HashMap <String, Object>(); data.put("id" , 1 ); data.put("name" , "John" ); return data; } }
响应状态码 默认情况下,Spring MVC的响应状态码由框架自动设置。但是,我们也可以在控制器方法中使用 @ResponseStatus 注解来指定特定的响应状态码。
1 2 3 4 5 6 7 8 9 10 @Controller public class TestController { @GetMapping("/status") @ResponseStatus(HttpStatus.OK) public void getStatus () { } }
使用ResponseEntity类封装响应 ResponseEntity是Spring框架提供的一个类,用于封装HTTP响应的内容、状态码和头部信息。它可以灵活地构建响应对象,并提供了一些便捷的方法来处理HTTP响应。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 @Controller public class TestController { @GetMapping("/ok") public ResponseEntity<String> ok () { return ResponseEntity.ok().build(); } @GetMapping("/success") public ResponseEntity<String> success () { String data = "访问成功!" ; return ResponseEntity.ok(data); } @PostMapping("/requestSuccess") public ResponseEntity<String> requestSuccess () { String data = "自定义数据" ; return ResponseEntity.status(HttpStatus.CREATED).body(data); } @GetMapping("/error") public ResponseEntity<String> error () { String errorMessage = "访问失败!" ; return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorMessage); } }
文件上传下载 文件上传 前端文件上传表单页面
1 2 3 4 <form action ="/upload" method ="post" enctype ="multipart/form-data" > <input type ="file" name ="file" /> <button type ="submit" > 上传</button > </form >
后端处理文件上传请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 @Controller public class FileUpload { @ResponseBody @PostMapping("/upload") public ResponseEntity<String> uploadFile (@RequestParam("file") MultipartFile file) { if (file.isEmpty()) { return ResponseEntity.badRequest().body("请选择要上传的文件" ); } try { String fileName = file.getOriginalFilename(); String substring = fileName.substring(fileName.lastIndexOf("." )); fileName = UUID.randomUUID().toString() + substring; String filePath = "/path/to/uploads/" ; File dest = new File (filePath + fileName); file.transferTo(dest); return ResponseEntity.ok("文件上传成功" ); } catch (IOException e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败:" + e.getMessage()); } } }
文件下载 前端下载链接
1 2 3 <a href ="/download1" > 下载文件</a > <a href ="/download2" > 下载文件</a > <a href ="/download3" > 下载文件</a >
后端处理文件下载请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 @RestController public class DownloadFile { @GetMapping("/download1") public void downloadFile1 (HttpServletResponse response) { String filePath = "/path/to/uploads/" ; String fileName = "example.txt" ; File file = new File (filePath + fileName); try (FileInputStream fis = new FileInputStream (file)) { response.setContentType("application/octet-stream" ); response.setHeader("Content-Disposition" , "attachment; filename=" + fileName); byte [] buffer = new byte [1024 ]; int len; while ((len = fis.read(buffer)) != -1 ) { response.getOutputStream().write(buffer, 0 , len); } response.flushBuffer(); } catch (IOException e) { e.printStackTrace(); } } @GetMapping("/download2") public ResponseEntity<byte []> downloadFile2() { String filePath = "/path/to/uploads/" ; String fileName = "example.txt" ; File file = new File (filePath + fileName); try { byte [] fileContent = new byte [(int ) file.length()]; FileInputStream fis = new FileInputStream (file); fis.read(fileContent); fis.close(); HttpHeaders headers = new HttpHeaders (); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentDispositionFormData("attachment" , fileName); return new ResponseEntity <>(fileContent, headers, HttpStatus.OK); } catch (IOException e) { e.printStackTrace(); return new ResponseEntity <>(HttpStatus.INTERNAL_SERVER_ERROR); } } @GetMapping("/download3") public ResponseEntity<FileSystemResource> downloadFile3 () { String filePath = "/path/to/uploads/" ; String fileName = "example.txt" ; File file = new File (filePath + fileName); HttpHeaders headers = new HttpHeaders (); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentDispositionFormData("attachment" , fileName); try { FileSystemResource resource = new FileSystemResource (file); return new ResponseEntity <>(resource, headers, HttpStatus.OK); } catch (Exception e) { e.printStackTrace(); return new ResponseEntity <>(HttpStatus.INTERNAL_SERVER_ERROR); } } }
拦截器(Interceptor) 拦截器简介 拦截器(Interceptor)是表现层框架(如 Spring MVC、Struts)自身提供的组件,在 Spring MVC 中,拦截器定义在 org.springframework.web.servlet 包下,用于拦截用户请求,并在请求到达目标处理程序(Controller)之前或之后执行相应的逻辑
拦截器实现 在 Spring MVC 中,拦截器通过实现 HandlerInterceptor 接口来定义,并重写其中的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true ; } @Override public void postHandle (HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
在Spring MVC中使用MyInterceptor拦截器,还需要在配置文件中进行相应的配置
1 2 3 4 5 6 7 8 9 10 <mvc:interceptors > <mvc:interceptor > <mvc:mapping path ="/**" /> <bean class ="com.wen.MyInterceptor" /> </mvc:interceptor > </mvc:interceptors >
拦截器链 拦截器链是指在一个请求被处理的过程中,多个拦截器按照一定的顺序依次执行的机制,执行顺序与它们在配置文件或代码中的注册顺序一致,XML配置如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <mvc:interceptors > <mvc:interceptor > <mvc:mapping path ="/path1/*" /> <bean class ="com.example.Interceptor1" /> </mvc:interceptor > <mvc:interceptor > <mvc:mapping path ="/path2/*" /> <bean class ="com.example.Interceptor2" /> </mvc:interceptor > <mvc:interceptor > <mvc:mapping path ="/path3/*" /> <bean class ="com.example.Interceptor3" /> </mvc:interceptor > </mvc:interceptors >
监听器、过滤器、拦截器的区别 功能定位 监听器 :主要用于监听和响应特定事件,对事件进行处理。过滤器 :用于对请求进行预处理和后处理,对请求和响应进行筛选和修改。拦截器 :在请求和响应的处理过程中,拦截并插入额外的逻辑来实现附加功能。使用场景 监听器 :适用于需要侦听和响应应用程序中的事件的情况,如服务器启动/关闭、会话的创建/销毁等。过滤器 :常用于对请求进行过滤和处理,如身份验证、请求参数处理、字符编码等。拦截器 :通常用于在应用程序级别上实现横切关注点,如日志记录、权限验证、性能监控等。执行顺序 监听器 :由事件的发生顺序决定的,是被动的组件,它通过事件监听机制等待特定事件的发生,并在事件触发时执行相应的处理逻辑过滤器 :过滤器通常形成一个过滤器链(Filter Chain),按照配置的顺序依次执行拦截器 :由框架或应用程序维护拦截器链,通过拦截器链中的调用顺序依次执行拦截器的前置和后置逻辑技术实现 监听器 :使用事件监听机制,通过实现特定接口或注解来定义监听器,并在配置文件或代码中进行注册。过滤器 :使用Servlet规范中的Filter接口,通过编写过滤器类并在配置文件中进行配置和映射。拦截器 :通常由框架或应用程序提供,通过定义拦截器类,并在配置或代码中进行配置和使用。