十七:Spring Boot依赖 (2)-- spring-boot-starter-web 依赖详解

目录

1. spring-boot-starter-web 简介

1.1 作用与功能:

1.2 引入方式:

1.3 包含的核心依赖:

2. 自动配置原理

3. 内嵌 Servlet 容器

3.1 默认 Tomcat 配置:

3.2 替换容器(Jetty 或 Undertow):

4. 构建 RESTful Web 服务:

4.1 什么是 RESTful Web 服务

4.2 创建 REST 控制器

5. 自动处理 JSON:

6. 静态资源支持

7. Web 配置定制(通过 WebMvcConfigurer)

7.1 注册拦截器(Interceptor)

7.2 配置静态资源处理

7.2.1 addResourceHandlers(ResourceHandlerRegistry registry) 方法

7.2.2 registry.addResourceHandler("/assets/**")

7.2.3 addResourceLocations("classpath:/static/assets/")

7.3 配置视图解析器(ViewResolver)

7.3.1 pom.xml 加两个引用 支持jsp 的

7.3.2 配置视图解析器

7.3.3 创建jsp页面

7.3.4 写controller 一定用@Controller

7.3.4 浏览器访问 乱码 无所谓 只要能请求到 就没大问题

7.3.5 工作原理

7.4 CORS 配置(跨域资源共享)

7.4.1 什么是跨域?

7.4.2 为什么会有跨域问题?

7.4.3 同源策略(Same-Origin Policy)

7.4.4 跨域的场景​​​​​​​

7.4.5 浏览器的跨域限制

7.4.6 跨域的解决方案

​​​​​​​7.4.6.1 CORS(跨域资源共享)

7.4.6.2 JSONP(仅限 GET 请求)

7.4.6.3 服务器端代理(推荐)

7.5 消息转换器(Message Converters)

7.8 定制异常处理(@ExceptionHandler)(不推荐)

8. 支持文件上传与下载

​​​​​​​8.1 文件上传

8.1.1 配置文件上传的基本设置

8.1.2 实现文件上传接口

8.1.3 上传目录配置

8.1.4 上传多个文件

8.2 文件下载

8.2.1 实现文件下载接口

8.2.2 设置响应头部以下载文件


  • 1. spring-boot-starter-web 简介

    • 1.1 作用与功能

      • spring-boot-starter-web 是 Spring Boot 的一个启动器(starter),用于构建 Web 应用,它自动配置了多种常见的 Web 组件,尤其适合构建 RESTful Web 服务。

    • 1.2 引入方式

      • Maven:在 pom.xml 中添加:
        • <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          
      • Gradle:在 build.gradle 中添加:
        • implementation 'org.springframework.boot:spring-boot-starter-web'
          
    • 1.3 包含的核心依赖

      • ​​​​​Spring MVC:构建 Web 应用的基础框架,提供了控制器、视图解析等功能。

      • 内嵌 Servlet 容器(Tomcat):提供一个内嵌的默认 Servlet 容器,简化部署。

      • Jackson:用于 JSON 数据的序列化和反序列化。

      • Spring Boot 自动配置:自动配置 DispatcherServlet,自动配置 Spring MVC 相关的功能。

  • 2. 自动配置原理

    • DispatcherServlet 自动配置
      • Spring Boot 会自动配置 DispatcherServlet,它是 Spring MVC 的核心,用于路由请求到适当的控制器方法。

    • Spring MVC 相关的自动配置
      spring-boot-starter-web 自动配置了 Spring MVC 所需的 MessageConverter、视图解析器等,简化了手动配置。

    • Tomcat 自动配置
      默认情况下,spring-boot-starter-web 使用 Tomcat 作为嵌入式容器,你可以通过配置改变容器(如使用 Jetty 或 Undertow)。

  • 3. 内嵌 Servlet 容器

    • 3.1 默认 Tomcat 配置

      • 默认内嵌容器是 Tomcat,并且默认端口是 8080

      • 可以通过 application.propertiesapplication.yml 修改端口:

        • server.port=8081
    • 3.2 替换容器(Jetty 或 Undertow)

      • 如果你不想使用 Tomcat,可以排除它并使用 Jetty 或 Undertow:

      • 排除 Tomcat:

        • <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><scope>provided</scope>
          </dependency>
          
      • 添加 Jetty 或 Undertow:

        • <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jetty</artifactId>
          </dependency>
          
  • 4. 构建 RESTful Web 服务:

    • 4.1 什么是 RESTful Web 服务

      •         REST(Representational State Transfer)是一种通过 HTTP 协议与 Web 服务交互的架构风格。RESTful Web 服务遵循一系列约定,通常使用 HTTP 方法(如 GET、POST、PUT、DELETE)来进行资源的创建、查询、更新和删除操作。每个资源通常由一个 URL 唯一标识,且资源的数据通常以 JSON 返回。
    • 4.2 创建 REST 控制器

      •         在 Spring Boot 中,构建 RESTful 服务的核心是 @RestController 注解。@RestController 是一个结合了 @Controller@ResponseBody 注解的注解,表示该类是一个控制器,且返回的内容会自动以 JSON 或 XML 格式返回(根据客户端请求的 Accept 头)。

      • package com.example.demo.controller;import org.springframework.web.bind.annotation.GetMapping;
        import org.springframework.web.bind.annotation.RequestMapping;
        import org.springframework.web.bind.annotation.RestController;@RestController
        @RequestMapping("/api")
        public class HelloController {@GetMapping("/hello")public String hello() {return "Hello, World!";}
        }
        
      • @RestController:表示该类是一个 REST 控制器,返回数据会被自动序列化为 JSON 格式。

      • @RequestMapping("/api"):为所有请求添加一个基础路径 /api

      • @GetMapping("/hello"):处理 GET 请求,当客户端访问 /api/hello 时,返回 "Hello, World!"

      • @PostMapping:处理 HTTP POST 请求,用于创建新用户。

      • @PutMapping:处理 HTTP PUT 请求,用于更新用户信息。

      • @DeleteMapping:处理 HTTP DELETE 请求,用于删除用户。

  • 5. 自动处理 JSON:

    • spring-boot-starter-web 默认集成了 Jackson 序列化和反序列化,自动将 Java 对象与 JSON 数据进行转换。

    • 你可以使用 @RequestBody 注解接收请求体中的 JSON 数据,使用 @ResponseBody 返回 JSON 数据。

  • 6. 静态资源支持

    • 默认情况下,Spring Boot 会从 /static/public/resources/META-INF/resources 目录提供静态资源。

    • 可以将静态文件(如 HTML、CSS、JavaScript、图片等)放入这些目录中,Spring Boot 会自动提供访问。

    • 自定义静态资源路径

      • 可以通过配置文件修改静态资源的根目录

      • spring.resources.static-locations=classpath:/custom-static/
        
  • 7. Web 配置定制(通过 WebMvcConfigurer

    • 在开发 Spring Web 应用时,WebMvcConfigurer 是一个非常常用的接口,它提供了一种灵活的方式来定制 Spring MVC 的行为。

    • 7.1 注册拦截器(Interceptor)

      • package com.lirui.springbootmoduledemo.config;import org.springframework.context.annotation.Configuration;
        import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
        import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
        public class WebConfig  implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册一个拦截器registry.addInterceptor(new WebInterceptor())// 设置拦截路径.addPathPatterns("/api/**")// 排除不需要拦截的路径.excludePathPatterns("/api/login", "/api/register");}
        }
        
        package com.lirui.springbootmoduledemo.config;import org.springframework.web.servlet.HandlerInterceptor;
        import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;public class WebInterceptor  implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 这里可以做一些拦截前的校验或操作System.out.println("preHandle: 请求即将到达Controller");// 返回true表示继续处理请求,false表示请求被拦截,不会继续执行return true; // 如果返回false,请求会被拦截,后续不会执行}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {// 请求处理之后,视图渲染之前调用System.out.println("postHandle: 请求已处理,视图渲染之前");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 请求处理完后,视图渲染完毕后调用(通常用于清理资源)System.out.println("afterCompletion: 请求完成后,视图渲染之后");}
        }
        

    • 7.2 配置静态资源处理

      • package com.lirui.springbootmoduledemo.config;import org.springframework.context.annotation.Configuration;
        import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
        import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
        import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
        public class WebConfig  implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册一个拦截器registry.addInterceptor(new WebInterceptor())// 设置拦截路径.addPathPatterns("/api/**")// 排除不需要拦截的路径.excludePathPatterns("/api/login", "/api/register");}@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {// 配置 /assets/** 请求,映射到 classpath:/static/assets/ 文件夹registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/static/assets/");// 配置 /images/** 请求,映射到 classpath:/static/images/ 文件夹registry.addResourceHandler("/images/**").addResourceLocations("classpath:/static/images/");}}
        

      • 7.2.1 addResourceHandlers(ResourceHandlerRegistry registry) 方法

        • addResourceHandlers 是 Spring MVC 提供的一个方法,用于配置静态资源的处理方式。ResourceHandlerRegistry 用来注册静态资源的访问路径和实际的资源位置。

        • addResourceHandlers 方法允许你定义一组 资源处理器(Resource Handlers),这些处理器负责处理静态资源请求并返回相应的资源。通过配置,Spring MVC 能够自动映射 URL 路径到实际的文件存放位置,从而提供静态文件的访问功能。

      • 7.2.2 registry.addResourceHandler("/assets/**")

        • registry.addResourceHandler("/assets/**")

        • addResourceHandler("/assets/**") 指定了一个 资源请求的映射路径,即用户访问 /assets/ 路径下的任何 URL(匹配 /assets/**)时,都会交给 Spring MVC 来处理。

          • ** 是一种通配符,表示匹配 /assets/ 后面所有的路径(包括子目录)。

          • 例如,访问 http://localhost:8080/assets/img/logo.png 或者 http://localhost:8080/assets/css/style.css 都会被映射到对应的静态资源文件。

      • 7.2.3 addResourceLocations("classpath:/static/assets/")

        • addResourceLocations("classpath:/static/assets/") 指定了 静态资源文件的实际存储路径classpath:/static/assets/ 是资源文件所在的路径。

        • classpath: 表示资源位置在类路径中。Spring Boot 默认会将静态资源放在 src/main/resources/static 目录下。所以如果你的静态文件在 src/main/resources/static/assets/ 目录下,路径应该设置为 classpath:/static/assets/

        • 这样,当用户请求 /assets/** 路径时,Spring 会在 classpath:/static/assets/ 目录中查找对应的文件。

    • 7.3 配置视图解析器(ViewResolver)

      • 感觉很少会用到来
      • 7.3.1 pom.xml 加两个引用 支持jsp 的

        •         <dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><scope>provided</scope></dependency>
      • 7.3.2 配置视图解析器

        • package com.lirui.springbootmoduledemo.config;import org.springframework.context.annotation.Configuration;
          import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
          import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
          import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
          import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
          public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册一个拦截器registry.addInterceptor(new WebInterceptor())// 设置拦截路径.addPathPatterns("/api/**")// 排除不需要拦截的路径.excludePathPatterns("/api/login", "/api/register");}@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {// 配置 /assets/** 请求,映射到 classpath:/static/assets/ 文件夹registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/static/assets/");// 配置 /images/** 请求,映射到 classpath:/static/images/ 文件夹registry.addResourceHandler("/images/**").addResourceLocations("classpath:/static/images/");}@Overridepublic void configureViewResolvers(ViewResolverRegistry registry) {// 配置 JSP 视图解析器registry.jsp().prefix("/WEB-INF/views1/").suffix(".jsp");}}
          
      • 7.3.3 创建jsp页面

          • <!DOCTYPE html>
            <html lang="en">
            <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>hello</title>
            </head>
            <body>
            <h1>欢迎</h1>
            <h1>欢迎</h1>
            <h1>欢迎</h1>
            <h1>欢迎</h1>
            </body>
            </html>
            
      • 7.3.4 写controller 一定用@Controller

        • package com.lirui.springbootmoduledemo.controller;import org.springframework.stereotype.Controller;
          import org.springframework.web.bind.annotation.GetMapping;
          import org.springframework.web.bind.annotation.RequestMapping;
          import org.springframework.web.bind.annotation.RestController;@Controller
          @RequestMapping("/api")
          public class HelloController {@GetMapping("/hello")public String hello() {return "Hello, World!";}@GetMapping("/helloJSP")public String home() {// 返回 index.jsp 视图return "hello";}}
      • 7.3.4 浏览器访问 乱码 无所谓 只要能请求到 就没大问题

      • 7.3.5 工作原理

        • 当 Spring MVC 中的控制器(Controller)返回一个视图名称时(比如 "hello"),视图解析器会根据配置的 prefixsuffix 来构造最终的 JSP 文件路径。

          • 控制器返回视图名称:hello
          • 视图解析器会去 WEB-INF/views/ 目录下查找名为hello.jsp的文件。
          • 如果文件存在,Spring 会将该 JSP 文件渲染到响应中,返回给客户端。
    • 7.4 CORS 配置(跨域资源共享)

      • 7.4.1 ​​​​​​​什么是跨域?

        • ​​​​​​​**跨域(Cross-Origin)**是指浏览器在不同的域、协议、端口之间进行资源请求的行为。简单来说,当一个网页试图从不同的域名、端口号或协议(如 http://example.comhttps://example.com)加载资源时,就涉及到“跨域”问题。

      • 7.4.2 为什么会有跨域问题?

        • ​​​​​​​浏览器出于安全考虑,采用了 同源策略(Same-Origin Policy),即一个网页只能访问同一来源(同协议、同域名、同端口)的资源。这是为了防止恶意网站通过脚本获取用户的敏感数据或做其他恶意操作。

      • 7.4.3 同源策略(Same-Origin Policy)​​​​​​​

        • 协议httphttps
        • 域名:如 example.com
        • 端口:如 8080
        • 同源策略要求这三者必须完全相同才能进行资源的访问和交互。例如,https://example.comhttp://example.com 是不同的源,因为协议不同;http://example.com:8080http://example.com:9090 是不同的源,因为端口不同。
      • 7.4.4 跨域的场景​​​​​​​

        • 不同的域

          • 网站 A(https://site-a.com)想要访问网站 B(https://site-b.com)的资源。
        • 不同的协议

          • 网站 A(http://site.com)想要访问网站 B(https://site.com)的资源,协议不同。
        • 不同的端口

          • 网站 A(http://site.com:8080)想要访问网站 B(http://site.com:9090)的资源,端口不同。
      • 7.4.5 浏览器的跨域限制

        • ​​​​​​​​​​​​​​浏览器出于安全原因,限制了网页脚本对跨域资源的访问。比如,如果你的网页在 http://localhost:3000 上,试图去请求 http://api.example.com 上的资源,浏览器会默认阻止这种请求,称为 跨域请求(Cross-Origin Request)

          跨域请求的类型

          跨域请求可以分为两种类型:

          • 简单请求(Simple Request)

            • 请求方法是 GETPOSTHEAD

            • 请求头只包括浏览器内置的标准头部(如 Content-Type 设置为 application/x-www-form-urlencodedmultipart/form-datatext/plain)。

          • 复杂请求(Preflighted Request)

            • 请求方法是 PUTDELETE 或自定义的方法,或者请求头包含了非标准的自定义头部(例如 AuthorizationX-Custom-Header 等)。

            • 在这种情况下,浏览器会先发送一个 预检请求(Preflight Request),以确认服务器是否允许实际的请求。

      • 7.4.6 跨域的解决方案

        • ​​​​​​​7.4.6.1 CORS(跨域资源共享)
          • CORS(Cross-Origin Resource Sharing) 是一种浏览器和服务器之间的协议,它允许服务器声明哪些源(域、协议、端口)可以访问其资源。

          • 当浏览器发起跨域请求时,浏览器会自动添加一些 CORS 相关的头部信息:

            • Origin:表示请求发起的源(域、协议、端口)。

            • Access-Control-Allow-Origin:服务器响应的头部,表示允许哪些源可以访问资源。

          • CORS 预检请求: 当浏览器发起一个复杂的跨域请求时(例如,方法是 PUTDELETE 或请求头包含自定义头),浏览器会先发起一个 OPTIONS 请求,即 预检请求(Preflight Request),询问服务器是否允许跨域请求。如果服务器返回适当的响应头,则允许实际请求的发送。

          • CORS 响应头

            • Access-Control-Allow-Origin:允许访问的源,* 表示所有域都可以访问,或者可以指定特定的域(如 http://example.com)。

            • Access-Control-Allow-Methods:允许的 HTTP 方法(如 GET, POST, PUT, DELETE)。

            • Access-Control-Allow-Headers:允许的请求头。

            • Access-Control-Allow-Credentials:是否允许带上身份凭证(如 Cookies)。

            • Access-Control-Max-Age:预检请求的有效时间,表示浏览器在多长时间内不需要再次发送预检请求。

          •    @Overridepublic void addCorsMappings(CorsRegistry registry) {// 配置全局跨域registry.addMapping("/**").allowedOrigins("http://example.com") // 允许来自 example.com 的跨域请求.allowedMethods("GET", "POST") // 允许的请求方法.allowedHeaders("*"); // 允许所有请求头}
        • 7.4.6.2 JSONP(仅限 GET 请求)
          • 在早期,浏览器没有支持 CORS 机制时,开发者常用 JSONP 来绕过跨域限制。JSONP 是通过 <script> 标签的跨域特性来发送请求的,但它只支持 GET 请求,不支持发送其他类型的请求,如 POST

        • 7.4.6.3 服务器端代理(推荐)
          • 一种常见的解决跨域问题的方式是通过设置 代理服务器。前端应用发送请求到同源的代理服务器,由代理服务器转发请求到实际的跨域资源服务器。代理服务器和跨域服务器之间的请求不受浏览器的同源策略限制。

    • 7.5 消息转换器(Message Converters)

      • ​​​​​​​Spring MVC 使用 HttpMessageConverter 来将请求和响应的主体内容转换成 Java 对象或从 Java 对象转换为响应的格式(如 JSON、XML)。你可以定制消息转换器来支持自定义的序列化方式。

      • @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {// 创建 Jackson 转换器MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();// 创建 ObjectMapper 并进行配置ObjectMapper objectMapper = new ObjectMapper();// 排除 null 字段objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);// 设置日期格式objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));// 可以通过 Jackson 的 MixIn 来定制序列化规则objectMapper.addMixIn(SomeClass.class, SomeClassMixIn.class);// 设置 ObjectMapper 到 Jackson 转换器jacksonConverter.setObjectMapper(objectMapper);// 添加到转换器列表converters.add(jacksonConverter);
        }
    • 7.8 定制异常处理(@ExceptionHandler)(不推荐)

      • ​​​​​​​
        @Configuration
        public class WebConfig implements WebMvcConfigurer {@Overridepublic void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {// 定制异常处理resolvers.add(new MyCustomExceptionResolver());}
        }
  • 8. 支持文件上传与下载

    • ​​​​​​​8.1 文件上传

      • 8.1.1 配置文件上传的基本设置

        • 在 Spring Boot 中,文件上传的功能默认已经启用。但是,你可以在 application.propertiesapplication.yml 中配置一些上传限制(如文件大小)。
        • # 最大上传文件大小
          spring.servlet.multipart.max-file-size=10MB
          # 最大请求数据大小
          spring.servlet.multipart.max-request-size=10MB
          
      • 8.1.2 实现文件上传接口

        • @RestController
          @RequestMapping("/api/files")
          public class FileUploadController {@Value("${file.upload-dir}")private String uploadDir;  // 用于存储文件的目录// 文件上传接口@PostMapping("/upload")public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {try {// 获取文件名String fileName = file.getOriginalFilename();// 将文件存储到指定目录Path path = Paths.get(uploadDir, fileName);Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);return ResponseEntity.ok("文件上传成功:" + fileName);} catch (IOException e) {e.printStackTrace();return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败:" + e.getMessage());}}
          }
          
      • 8.1.3 上传目录配置

        • 你可以在 application.properties 文件中指定文件上传的目录。例如:
        • # 文件存储路径
          file.upload-dir=./uploads
          
      • 8.1.4 上传多个文件

        • @PostMapping("/uploadMultiple")
          public ResponseEntity<String> uploadMultipleFiles(@RequestParam("files") List<MultipartFile> files) {for (MultipartFile file : files) {// 保存每个文件try {String fileName = file.getOriginalFilename();Path path = Paths.get(uploadDir, fileName);Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);} catch (IOException e) {e.printStackTrace();return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("部分文件上传失败:" + e.getMessage());}}return ResponseEntity.ok("所有文件上传成功");
          }
          
    • 8.2 文件下载

      • 8.2.1 实现文件下载接口

        • 下载文件的实现比较简单,通常使用 HttpServletResponse 来将文件内容写入响应流中,浏览器会自动处理并触发文件下载。

        • @RestController
          @RequestMapping("/api/files")
          public class FileDownloadController {@Value("${file.upload-dir}")private String uploadDir;  // 文件存储目录// 文件下载接口@GetMapping("/download/{fileName}")public ResponseEntity<Resource> downloadFile(@PathVariable String fileName) {try {// 获取文件路径Path filePath = Paths.get(uploadDir).resolve(fileName).normalize();// 如果文件不存在,抛出异常Resource resource = new FileSystemResource(filePath);if (!resource.exists()) {throw new FileNotFoundException("文件未找到:" + fileName);}// 返回文件资源并设置下载的 Content-Dispositionreturn ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"").body(resource);} catch (Exception e) {e.printStackTrace();return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);}}
          }
          
      • 8.2.2 设置响应头部以下载文件

        • 通过 Content-Disposition 响应头可以让浏览器以下载的形式处理文件而不是直接显示内容。上述代码中已经设置了这个头部:

        • .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
          

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/10518.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Python注意力机制Attention下CNN-LSTM-ARIMA混合模型预测中国银行股票价格|附数据代码...

全文链接&#xff1a;https://tecdat.cn/?p38195 股票市场在经济发展中占据重要地位。由于股票的高回报特性&#xff0c;股票市场吸引了越来越多机构和投资者的关注。然而&#xff0c;由于股票市场的复杂波动性&#xff0c;有时会给机构或投资者带来巨大损失。考虑到股票市场的…

MySQL中的INT(4)里面的4究竟代表着什么

目录 1. 理解INT类型中的数字2. INT显示宽度与INSERT操作3. SELECT、INSERT、UPDATE、DELETE与显示宽度4. 实际应用中的影响场景5. 创建表时的建议 1. 理解INT类型中的数字 在MySQL中&#xff0c;当你定义一个整数字段为INT(M)&#xff0c;这里的M代表的是显示宽度。 这个数字…

Spring Boot实现的工程认证计算机课程管理解决方案

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理基于工程教育认证的计算机课程管理平台的相…

中药香料价钱快速划价计算器软件 中药文本识别计算费用管理系统操作教程

一、概述 【软件试用版资源文件下载可点文章最后官网卡片了解】 中药香料价钱快速划价计算器软件 中药文本识别计算费用管理系统操作教程 ‌核心功能‌&#xff1a;快速划价与账单管理。 ‌快速划价‌&#xff1a;复制药方文本&#xff0c;点击划价按钮即可计算总金额‌。‌账…

代码随想录刷题记录(二十五)——54. 替换数字

&#xff08;一&#xff09;问题描述 54. 替换数字&#xff08;第八期模拟笔试&#xff09;https://kamacoder.com/problempage.php?pid1064给定一个字符串 s&#xff0c;它包含小写字母和数字字符&#xff0c;请编写一个函数&#xff0c;将字符串中的字母字符保持不变&#…

【温度表达转化】

【温度表达转化】 C语言代码C代码Java代码Python代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 利用公式 C5∗(F−32)/9 &#xff08;其中C表示摄氏温度&#xff0c;F表示华氏温度&#xff09; 进行计算转化。 输出 输出一行&#x…

【时间之外】IT人求职和创业应知【32】-RTE二次出现

目录 新闻一&#xff1a;AI-AGENT加速落地&#xff0c;计算机行业利润端好转 新闻二&#xff1a;声网CEO赵斌&#xff1a;RTE将成为生成式AI时代AI Infra的关键部分 新闻三&#xff1a;11月科技盛会&#xff1a;新技术与产品发布一览 认知和思考决定了你的赚钱能力。以下是今…

基于51单片机的温控电风扇proteus仿真

地址&#xff1a;https://pan.baidu.com/s/1vgYgY41tp_axxVFTHAPwFg 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectron…

Spring 配置绑定原理分析

Spring 配置绑定原理分析 前言 Spring 应用中存在诸多配置&#xff0c;有的是系统配置&#xff0c;有的命令行启动参数配置&#xff0c;有的是yaml配置&#xff0c;有的是分布式配置中心配置&#xff0c;但对使用者而言总是可以通过ConfigurationProperties将它关联到一个Java…

Hadoop生态圈框架部署(五)- Zookeeper完全分布式部署

文章目录 前言一、Zookeeper完全分布式部署&#xff08;手动部署&#xff09;1. 下载Zookeeper2. 上传安装包2. 解压zookeeper安装包3. 配置zookeeper配置文件3.1 创建 zoo.cfg 配置文件3.2 修改 zoo.cfg 配置文件3.3 创建数据持久化目录并创建myid文件 4. 虚拟机hadoop2安装并…

HarmonyOS Next 实战卡片开发 03

HarmonyOS Next 实战卡片开发 03 在前面两张&#xff0c;我们基本掌握了卡片的使用流程&#xff0c;本章节就通过一个实战来加强对卡片使用的理解。 要完成的案例 新建项目和新建服务卡片 设置沉浸式 entry/src/main/ets/entryability/EntryAbility.ets 首页显示轮播图数据 1…

基于 PyTorch 从零手搓一个GPT Transformer 对话大模型

一、从零手实现 GPT Transformer 模型架构 近年来&#xff0c;大模型的发展势头迅猛&#xff0c;成为了人工智能领域的研究热点。大模型以其强大的语言理解和生成能力&#xff0c;在自然语言处理、机器翻译、文本生成等多个领域取得了显著的成果。但这些都离不开其背后的核心架…

三、整数规划

整数规划 建立逻辑变量来整合多个方案。如0-1变量&#xff08;要说明0和1分别表示什么&#xff09;见P79求解纯整数规划的分支定界法&#xff1a; 求解整数规划的松弛问题的最优解若松弛问题的最优解满足整数要求&#xff0c;则得到整数规划的最优解&#xff0c;否则转下一步任…

Docker了解

Docker是一种容器化技术&#xff0c;它可以将应用程序和其依赖项打包到一个独立的、可移植的容器中&#xff0c;以便在不同的环境中运行。Docker基于Linux操作系统的容器化技术&#xff0c;可以提供更轻量、更快速、更灵活、更一致的应用部署和管理方式。 Docker的基本概念包括…

stm32以太网接口:MII和RMII

前言 使用stm32和lwip进行网络通信开发时&#xff0c;实现结构如下&#xff1a; 而MII和RMII就是stm32与PHY芯片之间的通信接口&#xff0c;类似于I2C、UART等。 stm32以太网模块有专用的DMA控制器&#xff0c;通过AHB接口将以太网内核和存储器相连。 数据发送时&#xff0c;…

【GESP】C++一级真题练习(202312)luogu-B3921,小杨的考试

GESP一级真题练习。为2023年12月一级认证真题。逻辑计算问题。 题目题解详见&#xff1a;【GESP】C一级真题练习(202312)luogu-B3921&#xff0c;小杨的考试 | OneCoder 【GESP】C一级真题练习(202312)luogu-B3921&#xff0c;小杨的考试 | OneCoderGESP一级真题练习。为2023…

【java】通过<类与对象> 引入-> 链表

目录 链表 碎片化&#xff1a; 内存碎片产生的原因 如何避免内存碎片&#xff1f; 链表类型 单链表 双链表 单循环链表 双循环链表 java是如何创建链表的&#xff1f; 类与对象 类是什么&#xff1f; 什么是对象&#xff1f; 构建链表 头指针 简画内存图&#…

微软开源5级Agent框架,复杂任务就这么被解决了~

微软又来卷Agent&#xff0c;开源了解决复杂任务的通用Multi-Agent框架Magentic-One&#xff0c;它旨在解决开放性的网络和基于文件的任务&#xff0c;跨越各种领域&#xff0c;如操作网络浏览器、导航本地文件、编写和执行Python代码、做市场调研、写论文等等。 Magentic-One…

矩阵中的路径(dfs)-acwing

题目 23. 矩阵中的路径 - AcWing题库 代码 class Solution { public://以每一个坐标作为dfs起点bool hasPath(vector<vector<char>>& matrix, string str) {for (int i 0; i < matrix.size(); i )for (int j 0; j < matrix[i].size(); j )if (dfs(…

欢迎 Stable Diffusion 3.5 Large 加入 Diffusers

作为Stable Diffusion 3的改进版本&#xff0c;Stable Diffusion 3.5 如今已在 Hugging Face Hub 中可用&#xff0c;并可以直接使用 &#x1f9e8; Diffusers 中的代码运行。 https://hf.co/blog/sd3 本次发布包含两套模型参数: https://hf.co/collections/stabilityai/stable…