SpringMVC03-HttpMessageConverter(自定义消息转换器)

2,227 阅读2分钟

一、介绍

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>