springMVC-HTTP消息转换器与文件上传、下载、异常处理

HttpMessageConverter(HTTP消息转换器)

HTTP消息转换器主要是将请求的表单数据封装成对象,controller中的方法直接用对象接收数据。

HttpMessageConverter接口可以将请求协议转换为Java对象,也可以把Java对象转换为响应协议。

对于程序员来说,springmvc已经帮我们写好了,我们只需要在不同的业务场景下,选择合适的HTTP消息转换器即可。

我们可以使用不同的注解来启用不同的消息转换器。

@ResponseBody

这里使用的消息转换器是:StringHttpMessageConverter

java 复制代码
@GetMapping("/ajax")
// @ResponseBody注解表示该方法的返回值直接作为字符串响应体返回,而不是视图名称
@ResponseBody
public String ajax() {
    return "hello ajax";
}

直接返回Java对象,(这里使用的消息转换器是MappingJackson2HttpMessageConverter):

java 复制代码
@GetMapping("/ajax2")
// @ResponseBody注解表示该方法的返回值直接作为响应体返回,而不是视图名称
@ResponseBody
public User ajax2() {
    return new User("zhangsan", 20, "123456");
}

此时要加入jackson-databind依赖才能生效

xml 复制代码
 <!--  负责将Java对象转换为JSON格式,或者将JSON格式的数据转换为Java对象。
    它提供了丰富的功能和灵活的配置选项,使得在Java应用程序中处理JSON数据变得非常方便。-->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.20.2</version>
    </dependency>
</dependencies>

@RestController

标注在类上,等于@Controller+@ResponseBody

@RequestBody

作用是直接将请求体传递给Java程序,程序中可以直接使用一个String类型的变量来接收。

此注解只能出现在方法的参数上。

使用的消息转换器是FormHttpMessageConverter

java 复制代码
@PostMapping("/ajax3")
public String ajax3(@RequestBody String params) {
    System.out.println(params);
    return "hello ajax3";
}

如果前端请求体当中提交的数据是JSON格式,那么**@RequestBody可以将提交的json格式的字符串转换成Java对象**。同样需要使用jackson的依赖

java 复制代码
@PostMapping("/ajax4")
@ResponseBody
public String ajax4(@RequestBody User user) {
    System.out.println(user);
    return "hello ajax4";
}

RequestEntity类

RequestEntity类的实例封装了整个请求的协议:包括请求行、请求头、请求体的所有信息。

出现在控制器方法的参数上:

java 复制代码
@PostMapping("/ajax5")
@ResponseBody
public String ajax5(RequestEntity<User> requestEntity) {
    // 请求方式
    HttpMethod method = requestEntity.getMethod();
    // 请求体
    User user = requestEntity.getBody();
    // 请求头
    HttpHeaders headers = requestEntity.getHeaders();
    // 请求URL
    requestEntity.getUrl();
    // 请求头中的Content-Type
    headers.getContentType();
    return "hello ajax5";
}

ResponseEntity类

ResponseEntity类的实例可与封装响应协议,包括状态行、响应头、响应体。如果你想定制属于自己的响应协议,可以使用该类。注意:返回值必须是ResponseEntity ,泛型为什么是User。因为响应体的内容是User类型。

比如:

java 复制代码
@GetMapping("ajax6/{id}")
public ResponseEntity<User> ajax6(@PathVariable("id") String id) {
    User user =userService.getUserById(id);
    if (user == null) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
    }else{
        return ResponseEntity.ok(user);
    }
}

文件上传与下载

文件上传

添加以下依赖(SpringMVC6不需要添加依赖):

xml 复制代码
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.5</version>
</dependency>

文件上传必须是post请求

文件上传呢的form标签中必须使用enctype="multipart/form-data"

enctype是用来设置请求头的,默认是application/x-www-form-urlencoded

xml 复制代码
<!--    前端控制器-->
    <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.xml</param-value>
        </init-param>
        <load-on-startup>0</load-on-startup>
        <multipart-config>
<!--            设置单个文件的最大大小,单位为字节。超过这个大小的文件将被拒绝上传。-->
            <max-file-size>102400</max-file-size>
<!--            设置整个表单的最大大小,单位为字节。这个值包括所有文件和表单数据的总和。超过这个大小的请求将被拒绝。-->
            <max-request-size>1024000</max-request-size>
<!--            设置最小的文件大小,单位为字节。小于这个大小的文件将被拒绝上传。-->
            <file-size-threshold>0</file-size-threshold>
        </multipart-config>
    </servlet>

重点:在web.xml文件中DispatcherServlet配置时,添加multipart-config配置信息。(这是spring6的配置,如果是以前的版本。则不是这样配置)

前端代码:

html 复制代码
<form th:action="@{/file-upload}" method="post" enctype="multipart/form-data">
    <input type="file" name="file"/>
    <button type="submit">上传</button>

</form>

后端代码:

java 复制代码
@PostMapping("/file-upload")
public String file(@RequestParam("file") MultipartFile file) throws IOException {
    // 获取参数名
    String name = file.getName();
    // 获取文件大小
    long size = file.getSize();
    // 获取文件类型
    String contentType = file.getContentType();
    // 获取原始文件名
    String originalFilename = file.getOriginalFilename();
    // 获取文件输入流
    InputStream inputStream = file.getInputStream();
    // 创建一个缓冲输入流对象,用于读取文件内容
    BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
    // 创建一个新的文件名,使用当前时间戳加上原始文件的扩展名
    String newName = System.currentTimeMillis() + originalFilename.substring(originalFilename.lastIndexOf("."));
    String path = "D:/" + newName;
    // 创建一个缓冲输出流对象,用于将文件内容写入到指定路径
    File file1 = new File(path);
    BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
            new FileOutputStream(file1)
    );
    byte[] bytes = new byte[1024];
    int length = 0;
    // 循环读取文件内容,并将其写入到指定路径
    while ((length = bufferedInputStream.read(bytes)) != -1) {
        bufferedOutputStream.write(bytes, 0, length);
    }
    bufferedOutputStream.flush();
    // 关闭输入流和输出流
    bufferedInputStream.close();
    bufferedOutputStream.close();
    return "ok";
}

文件下载

前端代码:

html 复制代码
<a th:href="@{/download}">文件下载</a>

后端代码:

java 复制代码
@GetMapping("/download")
public ResponseEntity<byte[]> download() throws IOException {
    // 读取文件内容
    File file = new File("D:/xxx.jpg");
    // 创建一个HttpHeaders对象,用于设置响应头信息
    HttpHeaders headers = new HttpHeaders();
    // 设置响应头中的Content-Type为application/octet-stream,表示下载文件的类型为二进制流
    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    // 设置响应头中的Content-Disposition为attachment,表示下载文件的方式为附件,并指定下载文件的名称为原始文件名
    headers.setContentDispositionFormData("attachment", file.getName());
    // 创建一个ResponseEntity对象,包含文件内容、响应头信息和HTTP状态码,并返回给客户端
    ResponseEntity<byte[]> builder = new ResponseEntity<byte[]>(Files.readAllBytes(file.toPath()), headers, HttpStatus.OK);
    return builder;
}

异常处理器

异常处理器的作用:处理器方法执行过程中出现了异常,跳转到对应的视图。在视图上展示友好信息。

核心接口:HandlerExceptionResolver。核心方法是resolveException,最终返回的ModelAndView视图对象。会跳转到指定页面。

HandlerExceptionResolver有2个常用的默认实现:

DefaultHandlerExceptionResolver 默认的异常处理器

SimpleHandlerExceptionResolver 自定义异常处理器

自定义异常处理器

自定义异常处理器需要使用:SimpleHandlerExceptionResolver

自定义异常处理器机制的两种方式:

  • 通过xml配置
  • 通过注解

配置文件方式

在springmvc.xml文件中添加如下配置

xml 复制代码
<!--    配置自定义异常处理器-->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <!--    这里可以配置很多种异常,只要发生异常,就会跳转到对应界面
                  配置异常类型和视图名称的映射关系-->
                <prop key="java.lang.ArithmeticException">error</prop>
            </props>
        </property>
         <!--   将当前发生的异常对象存储到request域中,属性名为ex,
        可以在error.html页面中通过${ex}获取异常对象-->
        <property name="exceptionAttribute" value="ex"/>
    </bean>

注解方式

java 复制代码
@ControllerAdvice
public class ExceptionController {

    @ExceptionHandler
    public String handleException(Exception e, Model model) {
        model.addAttribute("ex", e.getMessage());
        System.out.println("发生了异常:" + e.getMessage());
        return "error";
    }
}

控制器类使用@ControllerAdvice标注

具体的方法使用@ExceptionHandler标注

相关推荐
JavaGuide21 小时前
Claude Opus 4.6 真的用不起了!我换成了国产 M2.5,实测真香!!
java·spring·ai·claude code
玹外之音1 天前
Spring AI MCP 实战:将你的服务升级为 AI 可调用的智能工具
spring·ai编程
来一斤小鲜肉1 天前
Spring AI入门:第一个AI应用跑起来
spring·ai编程
NE_STOP1 天前
springMVC-常见视图组件与RESTFul编程风格
spring
what丶k2 天前
Spring AI 多模态开发全解析:从入门到企业级落地
后端·spring·ai编程
NE_STOP2 天前
springMVC-获取前端请求的数据与三个作用域
spring
莫寒清2 天前
Spring MVC:@PathVariable 注解详解
java·spring·mvc
-大头.2 天前
从 0 开始理解 Spring 的核心思想 —— IoC 和 DI(1)
spring
莫寒清2 天前
Apache Tika
java·人工智能·spring·apache·知识图谱