SpringMVC笔记之HttpMessageConverter

8 HttpMessageConverter

HttpMessageConverter,报文信息转换器,它有两个作用:

  1. 将请求报文转换为Java对象
  2. 或将Java对象转换为响应报文

HttpMessageConverter提供了两个注解和两个类型:@RequestBody,@ResponseBody,RequestEntity,@ResponseEntity

8.1 环境准备

首先,新建一个Moodle,然后修改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>org.example</groupId>
    <artifactId>rest_mvc</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <packaging>war</packaging>

    <dependencies>
        <!--SpringMVC-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.9</version>
        </dependency>

        <!--ServletAPI-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <!--Spring5和Thymeleaf整合包-->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.12.RELEASE</version>
        </dependency>
    </dependencies>

</project>

然后修改我们的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
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--扫描组件-->
    <context:component-scan base-package="com.zjw.mvc"/>

    <!--配置Thymeleaf视图解析器(针对h5文件,抄就完了)-->
    <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>

    <!--
        处理静态资源,如html、js、css、jpg
        若只设置该标签,则只访问静态资源,其他请求无法访问
        此时必须设置<mvc:annotation-driven/>解决问题
    -->
    <mvc:default-servlet-handler/>

    <!--开启mvc注解驱动-->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <!--处理响应中文乱码问题-->
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="defaultCharset" value="UTF-8"/>
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html</value>
                        <value>application/json</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
</beans>

编写一个首页页面index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
    <h1>首页</h1>
</form>
</body>
</html>

然后再编写一个成功跳转的页面success.html:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>成功页面</title>
</head>
<body>
  <h1>成功跳转</h1>
</body>
</html>

同时在springMVC加上这两个页面的view-controller:

   <mvc:view-controller path="/" view-name="index" />
   <mvc:view-controller path="/success" view-name="success" />

8.2 @RequestBody

@RequestBody可以获取请求体,需要在控制器方法设置一个形参,使用@RequestBody进行标识,当前请求的请求体就会为当前注解所标识的形参赋值。
首先在index页面增加一个表单:

<form th:action="@{/testRequestBody}" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit">
</form>

同时在Controller类中增加相应的控制器方法:

@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String requestBody){
    System.out.println("requestBody:"+requestBody);
    return "success";
}

在这里插入图片描述

此时控制台输出:
在这里插入图片描述
根据结果我们可以发现,输出的结果跟get方法地址栏的形式一样,key=value然后以?拼接

8.3 RequestEntity

RequestEntity封装请求报文的一种类型,需要在控制器方法的形参中设置该类型的形参,当前请求的请求报文就会赋值给该形参,可以通过getHeaders()获取请求头信息,通过getBody()获取请求体信息
在控制器类增加以下方法:

    @RequestMapping("/testRequestEntity")
    public String testRequestEntity(RequestEntity<String> requestEntity){
        System.out.println("requestHeader:"+requestEntity.getHeaders());
        System.out.println("requestBody:"+requestEntity.getBody());
        return "success";
    }

同时修改我们的index.html页面,增加以下表单:

<form th:action="@{/testRequestEntity}" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit">
</form>

输出内容:

在这里插入图片描述

8.4 @ResponseBody

@ResponseBody用于标识一个控制器方法,可以将该方法的返回值直接作为响应报文的响应体响应到浏览器

8.4.1 使用@ResponseBody返回一个字符串类型数据

在控制器类中加入以下方法:

    @RequestMapping("/testResponseBody")
    @ResponseBody
    public String testResponseBody(){
        return "success";
    }

然后在index页面,写一个跳转的超链接:

 <h2>测试ResponseBody传字符串</h2>
 <a th:href="@{/testResponseBody}">测试ResponseBody传字符串</a><br>

重启服务器

我们知道,如果没加@ResponseBody注解,我们应该跳转到success.html页面,但是,当加了ResponseBody注解后,显示的确实:
在这里插入图片描述
此时就相当于在之前JavaWeb中,在servlet中写了方法:

    public void testResponseBody(HttpServletResponse response) throws IOException {
        response.getWriter().write("success");
    }

8.4.2 使用@ResponseBody返回一个JSON类型数据

@ResponseBody处理json的步骤:

  1. 导入jackson的依赖

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.12.1</version>
    </dependency>
    
  2. 在SpringMVC的核心配置文件中开启mvc的注解驱动,此时在HandlerAdaptor中会自动装配一个消息转换器:MappingJackson2HttpMessageConverter,可以将响应到浏览器的Java对象转换为Json格式的字符串

    <mvc:annotation-driven />
    
  3. 在处理器方法上使用@ResponseBody注解进行标识

    @RequestMapping("/testResponseUser")
    @ResponseBody
    //随便新建一个User类即可,实现它的get,set和有参无参构造方法就可以
    public User testResponseUser(){
        return new User(1001,"admin","123456",23,"男");
    }
    
  4. 将Java对象直接作为控制器方法的返回值返回,就会自动转换为Json格式的字符串

  5. 在index编写超链接

     <h2>测试ResponseBody传JSON对象</h2>
     <a th:href="@{/testResponseUser}">测试ResponseBody传JSON对象</a><br>
    

在这里插入图片描述

8.4.3 @RestController注解

以后会很重要,很常用的一个注解——@RestController。这个注解是SpringMVC提供的一个复合注解,标识在控制器的类上,相当于为这个类添加@Controller注解,并且为这个类中所有的方法添加@ResponseBody注解

8.5 ResponseEntity类

ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文

使用ResponseEntity实现下载文件的功能
返回一个ResponseEntity,我们不仅要返回我们想要的响应内容,还需要给它加上响应头和状态码

首先将我们需要下载的图片放到webapp/static/img目录下
在这里插入图片描述

然会新建一个file.html来放置我们下载文件的超链接:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>文件的下载和上传</title>
</head>
<body>
<h2>测试文件下载</h2>
<a th:href="@{/testDownload}">点击下载SpringMVC.jpg</a><br>
</body>
</html>

在控制器类中加上file.html的控制器方法,以及文件下载的控制器方法

    @RequestMapping("/file")
    public String toFile(){
        return "file";
    }

    @RequestMapping("/testDownload")
    public ResponseEntity<byte[]> testDownload(HttpSession session) throws IOException {
        /*获取ServletContext对象*/
        ServletContext context = session.getServletContext();
        /*获取服务器中文件的真实路径*/
        String path = context.getRealPath("/static/img/SpringMVC.jpg");
        /*创建输入流*/
        InputStream inputStream = new FileInputStream(path);
        /*创建字节数组*/
        byte[] buffer = new byte[inputStream.available()];
        /*将流读取到字节数组中*/
        inputStream.read(buffer);
        /*创建HttpHeaders对象设置响应头信息*/
        MultiValueMap<String, String> headers = new HttpHeaders();
        /*设置下载的方式和文件名*/
        headers.add("Content-Disposition", "attachment;filename=SpringMVC.jpg");
        /*设置响应状态码*/
        HttpStatus status = HttpStatus.OK;
        /*创建ResponseEntity对象*/
        ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(buffer,headers,status);
        /*关闭输入流*/
        inputStream.close();
        return responseEntity;
    }

重启服务器:
在这里插入图片描述

在此基础去实现下载别的文件,只需修改以下两处代码:
在这里插入图片描述

8.6 SpringMVC实现文件上传

文件上传要求form表单的请求方式必须为post,并且添加属性enctype="multipart/form-data"(表示通过二进制形式传输,只有这样,服务器才能成功接收文件)SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息

上传步骤:

  1. 添加依赖:
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
  1. 在SpringMVC的配置文件中添加配置:
<!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
  1. 控制器方法:
@RequestMapping("/testUpload")
public String testUp(MultipartFile photo, HttpSession session) throws IOException {
    //获取上传的文件的文件名
    String fileName = photo.getOriginalFilename();
    //处理文件重名问题
    String hzName = fileName.substring(fileName.lastIndexOf("."));
    fileName = UUID.randomUUID().toString() + hzName;
    //获取服务器中photo目录的路径
    ServletContext servletContext = session.getServletContext();
    String photoPath = servletContext.getRealPath("photo");
    File file = new File(photoPath);
    if(!file.exists()){
        file.mkdir();
    }
    String finalPath = photoPath + File.separator + fileName;
    //实现上传功能
    photo.transferTo(new File(finalPath));
    return "success";
}
  1. 在file.html页面中增加以下代码:
  <h2>测试文件上传</h2>
    <!--
        enctype="multipart/form-data"表示通过二进制形式传输
        只有这样,服务器才能成功接收文件
    -->
    <form th:action="@{/testUpload}" method="post" enctype="multipart/form-data">
        图片:<input type="file" name="photo"><br>
        <input type="submit" value="提交">
    </form>
  1. 结果展示:
    在这里插入图片描述
    成功上传后跳到success.html页面
    在这里插入图片描述
    然后在target目录下查看我们上传的文件,文件名字是UUID自动生成防止名字重复:
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤独的偷学者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值