• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
james1207

博客园    首页    新随笔    联系   管理    订阅  订阅

封装fastjson为spring mvc的json view

可以将其中的main方法删掉。测试用的。我测试的结果是,jackson比fastjson快。

fastjson是1.1.36

jackson是2.2.3

jdk是1.7.40,client

cpu是intel i3

内存4g


package org.springframework.web.servlet.view.json;


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.servlet.view.AbstractView;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.test.User;

public class MappingFastJsonView extends AbstractView {
    
    /**
     * Default content type: "application/json".
     * Overridable through {@link #setContentType}.
     */
    public static final String DEFAULT_CONTENT_TYPE = "application/json";

    private String encoding = "UTF-8";
    
    private String jsonPrefix;

    private Boolean prettyPrint;

    private Set<String> modelKeys;

    private boolean extractValueFromSingleKeyModel = false;

    private boolean disableCaching = true;

    private boolean updateContentLength = false;


    /**
     * Construct a new {@code MappingFastJsonView}, setting the content type to {@code application/json}.
     */
    public MappingFastJsonView() {
        setContentType(DEFAULT_CONTENT_TYPE);
        setExposePathVariables(false);
    }
    
    public String getEncoding() {
        return encoding;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    /**
     * Specify a custom prefix to use for this view's JSON output.
     * Default is none.
     * @see #setPrefixJson
     */
    public void setJsonPrefix(String jsonPrefix) {
        this.jsonPrefix = jsonPrefix;
    }

    /**
     * Indicates whether the JSON output by this view should be prefixed with <tt>"{} && "</tt>.
     * Default is {@code false}.
     * <p>Prefixing the JSON string in this manner is used to help prevent JSON Hijacking.
     * The prefix renders the string syntactically invalid as a script so that it cannot be hijacked.
     * This prefix does not affect the evaluation of JSON, but if JSON validation is performed
     * on the string, the prefix would need to be ignored.
     * @see #setJsonPrefix
     */
    public void setPrefixJson(boolean prefixJson) {
//        if (prefixJson) {
//            if (jsonPrefix == null) {
//                jsonPrefix = "{} && ";
//            }
//        }
        this.jsonPrefix = (prefixJson ? "{} && " : null);
    }

    /**
     * Whether to use the default pretty printer when writing JSON.
     * This is a shortcut for setting up an {@code JSON}
     * <p>The default value is {@code false}.
     */
    public void setPrettyPrint(boolean prettyPrint) {
        this.prettyPrint = prettyPrint;
    }

    /**
     * Set the attribute in the model that should be rendered by this view.
     * When set, all other model attributes will be ignored.
     */
    public void setModelKey(String modelKey) {
        this.modelKeys = Collections.singleton(modelKey);
    }

    /**
     * Set the attributes in the model that should be rendered by this view.
     * When set, all other model attributes will be ignored.
     */
    public void setModelKeys(Set<String> modelKeys) {
        this.modelKeys = modelKeys;
    }

    /**
     * Return the attributes in the model that should be rendered by this view.
     */
    public final Set<String> getModelKeys() {
        return this.modelKeys;
    }
    
    /**
     * Set whether to serialize models containing a single attribute as a map or whether to
     * extract the single value from the model and serialize it directly.
     * <p>The effect of setting this flag is similar to using {@code MappingJacksonHttpMessageConverter}
     * with an {@code @ResponseBody} request-handling method.
     * <p>Default is {@code false}.
     */
    public void setExtractValueFromSingleKeyModel(boolean extractValueFromSingleKeyModel) {
        this.extractValueFromSingleKeyModel = extractValueFromSingleKeyModel;
    }

    /**
     * Disables caching of the generated JSON.
     * <p>Default is {@code true}, which will prevent the client from caching the generated JSON.
     */
    public void setDisableCaching(boolean disableCaching) {
        this.disableCaching = disableCaching;
    }

    /**
     * Whether to update the 'Content-Length' header of the response. When set to
     * {@code true}, the response is buffered in order to determine the content
     * length and set the 'Content-Length' header of the response.
     * <p>The default setting is {@code false}.
     */
    public void setUpdateContentLength(boolean updateContentLength) {
        this.updateContentLength = updateContentLength;
    }
    
    @Override
    protected void prepareResponse(HttpServletRequest request, HttpServletResponse response) {
        setResponseContentType(request, response);
        response.setCharacterEncoding(encoding);
        if (this.disableCaching) {
            response.addHeader("Pragma", "no-cache");
            response.addHeader("Cache-Control", "no-cache, no-store, max-age=0");
            response.addDateHeader("Expires", 1L);
        }
    }
    
    @Override
    protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        OutputStream stream = (this.updateContentLength ? createTemporaryOutputStream() : response.getOutputStream());
        Object value = filterModel(model);
        writeContent(stream, value, this.jsonPrefix);
        if (this.updateContentLength) {
            writeToResponse(response, (ByteArrayOutputStream) stream);
        }
    }

    /**
     * Filter out undesired attributes from the given model.
     * The return value can be either another {@link Map} or a single value object.
     * <p>The default implementation removes {@link BindingResult} instances and entries
     * not included in the {@link #setRenderedAttributes renderedAttributes} property.
     * @param model the model, as passed on to {@link #renderMergedOutputModel}
     * @return the value to be rendered
     */
    protected Object filterModel(Map<String, Object> model) {
        Map<String, Object> result = new HashMap<String, Object>(model.size());
        Set<String> renderedAttributes = (!CollectionUtils.isEmpty(this.modelKeys) ? this.modelKeys : model.keySet());
        for (Map.Entry<String, Object> entry : model.entrySet()) {
            if (!(entry.getValue() instanceof BindingResult) && renderedAttributes.contains(entry.getKey())) {
                result.put(entry.getKey(), entry.getValue());
            }
        }
        return (this.extractValueFromSingleKeyModel && result.size() == 1 ? result.values().iterator().next() : result);
    }

    /**
     * Write the actual JSON content to the stream.
     * @param stream the output stream to use
     * @param value the value to be rendered, as returned from {@link #filterModel}
     * @param jsonPrefix the prefix for this view's JSON output
     * (as indicated through {@link #setJsonPrefix}/{@link #setPrefixJson})
     * @throws IOException if writing failed
     */
    protected void writeContent(OutputStream stream, Object value, String jsonPrefix) throws IOException {
        
        List<SerializerFeature> list = new ArrayList<SerializerFeature>();
        if (prettyPrint != null && prettyPrint) {
            list.add(SerializerFeature.PrettyFormat);
        }
        
        SerializerFeature[] features = new SerializerFeature[list.size()];
        list.toArray(features);
        
        byte[] jsonBytes = JSON.toJSONBytes(value, features);
        
        if (jsonPrefix != null) {//此处亦可字符串相加,然后转成字节数组
            byte[] prefixBytes = jsonPrefix.getBytes(Charset.forName("UTF-8"));
            int prefixLength = prefixBytes.length;
            int jsonLength = jsonBytes.length;
            byte[] finalJsonBytes = new byte[prefixLength + jsonLength];
            
            System.arraycopy(prefixBytes, 0, finalJsonBytes, 0, prefixLength);
            System.arraycopy(jsonBytes, 0, finalJsonBytes, prefixLength, jsonLength);
            stream.write(finalJsonBytes);
        } else {
            stream.write(jsonBytes);
        }
        
        stream.flush();
    }
    
    public static void main(String[] args) {
        
        
        List<User> users = Lists.newArrayList();
        for (int j = 0; j < 10; j++) {
            User value = new User();
            value.setAddress("asdfjklasdjf");
            value.setAge(22);
            value.setGender(1);
            value.setPassword("jkljklj");
            value.setUserName("");
            
            List<String> strList = Lists.newArrayList();
            Map<String, String> strMap = Maps.newHashMap();
            Set<Integer> setInt = Sets.newHashSet();
            
            for (int i = 0; i < 10; i++) {
                strList.add("a" + i);
                strMap.put("a" + i, "a" + i);
                setInt.add(i);
            }
            
            value.setSetInt(setInt);
            value.setStrList(strList);
            value.setStrMap(strMap);
            users.add(value);
        }
        
        int times = 1;
//        long d = System.currentTimeMillis();
//        String jsonPrefix = "aaa{}";
//        
//        for (int i = 0; i < times; i++) {
//            byte[] jsonBytes = JSON.toJSONBytes(value);
//            byte[] prefixBytes = jsonPrefix.getBytes(Charset.forName("UTF-8"));
//            int prefixLength = prefixBytes.length;
//            int jsonLength = jsonBytes.length;
//            byte[] finalJsonBytes = new byte[prefixLength + jsonLength];
//            
//            System.arraycopy(prefixBytes, 0, finalJsonBytes, 0, prefixLength);
//            System.arraycopy(jsonBytes, 0, finalJsonBytes, prefixLength, jsonLength);
//        }
//        System.out.println(System.currentTimeMillis() - d);
        
        String json = "";
        String json2 = "";
        long d2 = System.currentTimeMillis();
        //String jsonPrefix2 = "aaa{}";
        for (int i = 0; i < times; i++) {
            json = JSON.toJSONString(users);
            
//            jsonBytes = jsonPrefix2 + jsonBytes;
//            
//            byte[] prefixBytes = jsonBytes.getBytes(Charset.forName("UTF-8"));
            
        }
        System.out.println("fastjson parser :" + (System.currentTimeMillis() - d2));
        
        ObjectMapper mapper = new ObjectMapper();
        
        //org.codehaus.jackson.map.ObjectMapper mapper = new org.codehaus.jackson.map.ObjectMapper();
        
        long d3 = System.currentTimeMillis();
        //String jsonPrefix3 = "aaa{}";
        for (int i = 0; i < times; i++) {
            //String jsonBytes = null;
            try {
                //StringWriter writer = new StringWriter();
                //JsonGenerator generator = new JsonFactory().createGenerator(writer);
                //mapper.writeValue(writer, value);
                //jsonBytes = writer.toString();
                json2 = mapper.writeValueAsString(users);
                //mapper.readValue(new StringReader(""), class1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            
//            jsonBytes = jsonPrefix3 + jsonBytes;
//            
//            byte[] prefixBytes = jsonBytes.getBytes(Charset.forName("UTF-8"));
            
        }
        System.out.println("jackson parser :" + (System.currentTimeMillis() - d3));
        
        long d5 = System.currentTimeMillis();
        for (int i = 0; i < times; i++) {
            JSON.parseArray(json, User.class);
        }
        System.out.println("fastjson deserializer :" + (System.currentTimeMillis() - d5));
        
        long d4 = System.currentTimeMillis();
        for (int i = 0; i < times; i++) {
            try {
                //List<User> userList = Lists.newArrayList();
                mapper.readValue(json2, new TypeReference<List<User>>() {});
//                List<User> userList = Lists.newArrayList();
//                for (;iterator.hasNext();) {
//                    userList.add(iterator.nextValue());
//                }
                //System.out.println(userList);
            } catch (JsonParseException e) {
                e.printStackTrace();
            } catch (JsonMappingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("jackson deserializer :" + (System.currentTimeMillis() - d4));
        
        
    }
    

}


package com.test;

import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class User {
    private String userName;
    private String address;
    private int age;
    private int gender;
    private String password;
    
    private List<String> strList;
    private Map<String, String> strMap;
    
    private Set<Integer> setInt;
    
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getGender() {
        return gender;
    }
    public void setGender(int gender) {
        this.gender = gender;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public List<String> getStrList() {
        return strList;
    }
    public void setStrList(List<String> strList) {
        this.strList = strList;
    }
    public Map<String, String> getStrMap() {
        return strMap;
    }
    public void setStrMap(Map<String, String> strMap) {
        this.strMap = strMap;
    }
    public Set<Integer> getSetInt() {
        return setInt;
    }
    public void setSetInt(Set<Integer> setInt) {
        this.setInt = setInt;
    }
    
    
}



posted @ 2013-09-17 23:21  Class Xman  阅读(1343)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3