Spring 4.2.4.RELEASE MVC 学习笔记 - 8.1 - text/gson(咋个办呢 zgbn)

4 篇文章 0 订阅
3 篇文章 0 订阅
本文介绍如何在Spring MVC框架中整合Gson工具,实现Restful API对JSON数据的支持。主要内容包括修改测试请求URL、调整UserController处理方法及自定义Gson数据解析器。
摘要由CSDN通过智能技术生成

Spring 4.2.4.RELEASE MVC 学习笔记 - 8.1 - text/gson

为了学习spring mvc框架整合fasterxml jackson工具,实现Restfull模式api实现对json、xml的支持。我们需要对之前对gson支持做一些改动,以免混淆视听。

修改测试请求URL

修改原来的user.html页面中的测试URL,将/api/userAdd.json修改为/api/userAdd.gson,/api/userQuery.json修改为/api/userQuery.gson。因为在Spring mvc 整合 fasterxml jackson工具的时候,框架上默认支持的一种情况就是以*.json为后缀的请求,这样修改避免弄混。
/framework_spring/src/main/webapp/user.html

<div class="vform">
            <div class="h1">HTTP POST 添加用户 /api/userAdd.gson</div>
            <form action="/api/userAdd.gson" method="post">
                <div>
                    <label>用户名:<input name="username" value="xiaohong" /></label>
                </div>
                <div>
                   <label> 姓名:<input name="name" value="小红" /></label>
                </div>
                <div>
                    <label>年龄:<input name="age" value="22" /></label>
                </div>
                <div>
                    <label>性别:<select name="sex"><option value="0" selected="selected"></option></select></label>
                </div>
                <div>
                    <button type="submit">添加新用户</button>
                </div>
            </form>
            <hr />
        </div>

        <div class="vform">
            <div class="h1">HTTP GET 查询用户 /api/userQuery.gson</div>
            <form action="/api/userQuery.gson" method="get">
                <div>
                   <label> 用户名:<input name="username" value="xiaohong" /></label>
                </div>
                <div>
                    <button type="submit">查询</button>
                </div>
            </form>
            <hr />
        </div>
        <div class="clearfloat"></div>
    </div>

修改UserController处理方法

修改原来UserController类中的方法userAddJson方法为userAddGson,同时修改对应的注解。详细参见下面的代码。
修改方法名字,属于个人习惯问题。
修改@RequestMapping注解,path = “/userAdd.gson”、produces = “text/gson; charset=UTF-8”,需要重点说明一下,path用于接收userAdd.gson过来的请求,produces则通过此信息控制调用自定义的Gson数据解析器解析数据。

cn.vfire.framework.spring.mvc.controller.UserController

@RequestMapping(path = "/userAdd.gson", method = RequestMethod.POST, produces = "text/gson; charset=UTF-8")
    @ResponseBody
    public Result userAddGson(UserMode user) {

        XModelAndView modeView = new XModelAndView();

        modeView.addObject("user", user);

        System.out.println(String.format("添加用户%s完成", user.getName()));

        return modeView.toResult();
    }

    @RequestMapping(path = "/userQuery.gson", method = RequestMethod.GET, produces = "text/gson; charset=UTF-8")
    @ResponseBody
    public Result userQueryGson(String username) {

        XModelAndView modeView = new XModelAndView();

        UserMode user = new UserMode();
        {
            user.setUsername(username);
            user.setName("小红");
            user.setAge(22);
            user.setSex(0);
        }

        modeView.addObject("user", user);

        System.out.println(String.format("查询用户名为%s用户 信息成功", user.getUsername()));

        return modeView.toResult();
    }

修改自定义数据解析器GSONHttpMessageConverte

修改原自定义Gson数据解析器GSONHttpMessageConverte类的构造方法,指定该解析器只处理MediaType=”text/gson; charset=UTF-8”的请求Requeset和应答Response。

cn.vfire.framework.spring.mvc.converter.GSONHttpMessageConverte

public GSONHttpMessageConverte(Charset defaultCharset) {
        super(new MediaType("text", "gson", defaultCharset));
        this.availableCharsets = DEFAULT_CHARSET;
        this.dateFormat = DEFAULT_DATEFORMAT;

        log.debug(String.format("注册自定义%s数据解析器,解析MediaType类型为%s。",GSONHttpMessageConverte.class.getName(),"application/json"));
        log.debug(String.format("默认处理字符集%s。",DEFAULT_CHARSET));
        log.debug(String.format("默认处理日期类型数据格式化%s。",DEFAULT_DATEFORMAT));
    }

PS:我偷偷的在这个类的方法中追加了日志打印,下面我还是列出该类的全部代码共大家参考把。
cn.vfire.framework.spring.mvc.converter.GSONHttpMessageConverte

package cn.vfire.framework.spring.mvc.converter;

import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import lombok.Getter;
import lombok.Setter;

import org.apache.log4j.Logger;
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.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

public class GSONHttpMessageConverte extends AbstractHttpMessageConverter<Object> {

    private static final Logger log = Logger.getLogger(GSONHttpMessageConverte.class);

    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    public static final String  DEFAULT_MEDIATYPE = "text/gson" ;

    public static final String DEFAULT_DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";

    private GsonBuilder gsonBuilder = new GsonBuilder();

    @Getter
    @Setter
    public  Charset charset = DEFAULT_CHARSET ;

    private List<MediaType> mediaTypes = new LinkedList<MediaType>() ;

    @Getter
    @Setter
    private String dateFormat = DEFAULT_DATEFORMAT;


    @Getter
    @Setter
    private boolean writeAcceptCharset = true;

    @Getter
    @Setter
    private boolean excludeFieldsWithoutExposeAnnotation = false;

    public GSONHttpMessageConverte() {
        this.setCharset(DEFAULT_CHARSET);
        this.setMediaTypes(DEFAULT_MEDIATYPE);
        this.setDateFormat(DEFAULT_DATEFORMAT);

        log.debug(String.format("注册自定义%s数据解析器,解析MediaType类型为%s。", GSONHttpMessageConverte.class.getName(), this.charset.toString()));
        log.debug(String.format("默认处理字符集%s。", DEFAULT_CHARSET));
        log.debug(String.format("默认处理日期类型数据格式化%s。", DEFAULT_DATEFORMAT));
    }

    protected List<Charset> getAcceptedCharsets() {
        List<Charset> charsetList = new ArrayList<Charset>(1);
        charsetList.add(this.charset);
        return charsetList;
    }

    @Override
    protected Long getContentLength(Object t, MediaType contentType) throws IOException {
        Long contentLength = super.getContentLength(t, contentType);
        log.debug("进入自定义" + GSONHttpMessageConverte.class.getName() + "数据解析器,内容长度为" + contentLength + "。");
        return contentLength;
    }

    private Charset getContentTypeCharset(MediaType contentType) {
        if (contentType != null && contentType.getCharSet() != null) {
            return contentType.getCharSet();
        } else {
            return this.charset;
        }
    }

    @Override
    public List<MediaType> getSupportedMediaTypes() {
        return Collections.unmodifiableList(this.mediaTypes);
    }

    @Override
    protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        Charset charset = this.getContentTypeCharset(inputMessage.getHeaders().getContentType());
        Object rs = StreamUtils.copyToString(inputMessage.getBody(), charset);

        log.debug(String.format("进入自定义%s数据解析器,处理字符集%s,读取数据流到到对象%s。", GSONHttpMessageConverte.class.getName(), String.valueOf(charset), String.valueOf(rs)));

        return rs;
    }

    public void setMediaTypes(List<String> mediaTypes) {
        if(mediaTypes!=null && mediaTypes.isEmpty()==false){
            for(String media : mediaTypes){
                this.setMediaTypes(media);
            }
        }
    }

    public void setMediaTypes(String mediaTypes) {
        if(this.mediaTypes.indexOf(mediaTypes)==-1){
            MediaType mt = MediaType.valueOf(mediaTypes);
            this.mediaTypes.add(new MediaType(mt.getType(),mt.getSubtype(),this.charset)) ;
        }
    }

    @Override
    protected boolean supports(Class<?> clazz) {
        return true;
    }

    private String toJson(Object o) {

        try {

            if (this.excludeFieldsWithoutExposeAnnotation) {
                this.gsonBuilder = this.gsonBuilder.excludeFieldsWithoutExposeAnnotation();
            }

            Type genericType = TypeToken.get(o.getClass()).getType();

            Gson gson = gsonBuilder.setDateFormat(this.dateFormat).create();

            String json = gson.toJson(o, genericType);

            if (json == null || "".equals(json.trim())) {
                json = "{}";
            }

            return json;

        } catch (Exception e) {
            e.printStackTrace();
        }

        return "";

    }

    @Override
    protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        if (this.writeAcceptCharset) {
            outputMessage.getHeaders().setAcceptCharset(this.getAcceptedCharsets());
        }
        Charset charset = this.getContentTypeCharset(outputMessage.getHeaders().getContentType());
        StreamUtils.copy(this.toJson(o), charset, outputMessage.getBody());

        log.debug(String.format("进入自定义%s数据解析器,处理字符集%s,解析对象%s到Json。", GSONHttpMessageConverte.class.getName(), String.valueOf(charset), String.valueOf(o)));

    }

}

测试

测试表单

这里写图片描述

后台日志

添加用户小红完成
@DEBUG|2016-03-08 12:28:28,755|cn.vfire.framework.spring.mvc.converter.GSONHttpMessageConverte.getContentLength(GSONHttpMessageConverte.java:72)|http-bio-8000-exec-6 
  Info:进入自定义cn.vfire.framework.spring.mvc.converter.GSONHttpMessageConverte数据解析器,内容长度为null。 

@DEBUG|2016-03-08 12:28:28,758|cn.vfire.framework.spring.mvc.converter.GSONHttpMessageConverte.writeInternal(GSONHttpMessageConverte.java:135)|http-bio-8000-exec-6 
  Info:进入自定义cn.vfire.framework.spring.mvc.converter.GSONHttpMessageConverte数据解析器,处理字符集UTF-8,解析对象cn.vfire.framework.spring.mvc.view.Result@1aa8430a到Json。 

结果页面

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值