一、介绍
HttpMessageConverter是用来处理request(请求)和response(响应)里的数据。
二、需求
自定义一个消息转换器,并注册这个HttpMessageConverter到SpringMVC中。
三、实现
1.新建DemoObj实体类
package com.eleven.domain;
public class DemoObj {
private Long id;
private String name;
public DemoObj() {
super();
}
public DemoObj(Long id, String name) {
super();
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.自定义HttpMessageConverter
package com.eleven.messageconverter;
import java.io.IOException;
import java.nio.charset.Charset;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.StreamUtils;
import com.eleven.domain.DemoObj;
public class MyMessageConverter extends AbstractHttpMessageConverter<DemoObj> { // 继承AbstractHttpMessageConverter接口实现自定义的HttpMessageConverterF
public MyMessageConverter() {
super(new MediaType("application", "x-eleven", Charset.forName("UTF-8")));// 自定义新建一个媒体类型application/x-eleven
}
/**
* 重写readInternal里面的方法,处理请求的数据。
* 用"-"隔开表示的数据,转换成DemoObj的对象。
*/
@Override
protected DemoObj readInternal(Class<? extends DemoObj> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
String temp = StreamUtils.copyToString(inputMessage.getBody(),
Charset.forName("UTF-8"));
String[] tempArr = temp.split("-");
return new DemoObj(new Long(tempArr[0]), tempArr[1]);
}
/**
* 声明这个HttpMessageConverter只处理DemoObj这个类
*/
@Override
protected boolean supports(Class<?> clazz) {
return DemoObj.class.isAssignableFrom(clazz);
}
/**
* 重写writeInternal方法,处理如何输出数据到response中。
* 并在前面原样输出hello
*/
@Override
protected void writeInternal(DemoObj obj, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
String out = "hello:" + obj.getId() + "-" + obj.getName();
outputMessage.getBody().write(out.getBytes());
}
}
3.添加addviewController添加映射访问地址
package com.eleven;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
import com.eleven.messageconverter.MyMessageConverter;
@Configuration // 声明当前类是一个配置类
@EnableWebMvc // 开启SpringMVC的注解
@ComponentScan("com.eleven") // 自动扫描包下面的注解和配置
public class MyMvcConfig extends WebMvcConfigurerAdapter {
/**
* 01-此处配置了JSP的,用来映射路径和实际页面的位置
*
* @return
*/
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/classes/views/");
viewResolver.setSuffix(".jsp");
viewResolver.setViewClass(JstlView.class);
return viewResolver;
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/index").setViewName("/index"); // 访问index页面
registry.addViewController("/toUpload").setViewName("/upload"); // 文件上传
registry.addViewController("/converter").setViewName("converter"); // 自定义消息转换器
}
/**
* 仅添加一个自定义的HttpMessageConverter,不会覆盖默认注册的HttpMessageConverter
*/
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(converter());
}
@Bean
public MyMessageConverter converter(){
return new MyMessageConverter();
}
}
3.编写ConverterController控制器
package com.eleven.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.eleven.domain.DemoObj;
@Controller // 返回的是字符串,一般都是与html页面渲染
public class ConverterController {
// 指定返回的媒体类型使我们自定义的媒体类型application/x-eleven
@RequestMapping(value = "/convert", produces = { "application/x-eleven" }) // 1
public @ResponseBody DemoObj convert(@RequestBody DemoObj demoObj) {
return demoObj;
}
}
4.新建converter.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HttpMessageConverter Demo</title>
</head>
<body>
<div id="resp"></div>
<input type="button" onclick="req();" value="请求" />
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
function req() {
$.ajax({
url : "convert",
data : "1-eleven", // 后台处理时,会用"-"隔开
type : "POST",
contentType : "application/x-eleven", // 自定义成application/x-eleven
success : function(data) {
$("#resp").html(data);
}
});
}
</script>
</body>
</html>
5.运行访问
输入地址:http://localhost:8080/springmvc02/converter
6.小插曲
问题:
Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported
解决:
参数contentType写成了contenType(此处诊真是4只眼都不够用了,奔走中。。。。)
问题:
jquery路径找不到,直接引用官方路径
解决:
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>