1. 程式人生 > >Spring 自定義HttpMessageConverter實現MongoDb自定義ObjectId物件為字串

Spring 自定義HttpMessageConverter實現MongoDb自定義ObjectId物件為字串

上週公司讓我做MongoDB的Document與json自定義相互轉換工作,具體就是

1.將後臺的Document直接返回給前臺,前臺接收到的是json資料,而且裡面的ObjectId是字串的形式:
“_id”:{ “$oid”: “598da5dd3888f020b164b25f” } 轉成 “_id”:”598da5dd3888f020b164b25f”

2.前臺傳入後臺的處理和上面相反:
_id”:”598da5dd3888f020b164b25f” 轉成 “_id”:{ “$oid”: “598da5dd3888f020b164b25f” }

其他都不變。

舉例來講:
前臺傳入的json字串:
{“name”:”張三111111”,”_id”:”598da5dd3888f020b164b25f”,”position”:”遼寧”,”age”:28}

後臺controller中:

@RequestMapping(value="/findone")
    public Document findOne(@RequestBody Document document) throws Exception{

        System.out.println("傳進來的Document-->"+document);
        System.out.println("傳進來的Document.toJson--->"+document.toJson());

        String collection = "hos_user_info"
; String id = "598da5dd3888f020b164b25f"; Document doc = service.queryById(collection, id); System.out.println("findOne(),doc.toString---->"+doc); System.out.println("findOne(),doc.toJson()---->"+doc.toJson()); return doc; }

直接用Document,接收入參,直接返回Document物件。同時前臺收到的是json字串,而且id是字串形式。

所以,此處就需要自定義json 的轉換器了:

1.自定義類DocumentHttpMessageConverter,繼承AbstractHttpMessageConverter。
具體程式碼:

public class DocumentHttpMessageConverter extends AbstractHttpMessageConverter<Document> {

    private Logger logger = LoggerFactory.getLogger(DocumentHttpMessageConverter.class);

    public DocumentHttpMessageConverter() {
        super(new MediaType("application", "json", Charset.forName("UTF-8")));       //自定義的型別:application/json
    }

    @Override
    protected boolean supports(Class<?> clazz) {
        return Document.class.isAssignableFrom(clazz);      //只支援Document物件
    }


    /**
     * @Author 
     * @Date 9:58 八月 24 0024
     * @Description: 讀取請求資料,構造Document物件,將輸入的json(ObjectId以字串形式)中"_id": "59915afa19191fcffc24a1d9"  改成:  "_id": { "$oid": "59915afa19191fcffc24a1d9" }格式,以用於轉化成Document物件
     */
    @Override
    protected Document readInternal(Class<? extends Document> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        String inputjson = StreamUtils.copyToString(inputMessage.getBody(), Charset.forName("UTF-8"));
        System.out.println("inputstream"+inputjson);
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(ObjectId.class, new ObjectIdDeserializer());
        mapper.registerModule(module);
        ObjectId oid = mapper.readValue(inputjson, ObjectId.class);
        inputjson = inputjson.replace("\"" + oid.toString() + "\"", "{ \"$oid\": \"" + oid.toString() + "\" }");

        System.out.println("輸入資料自動轉換>"+inputjson);

        return Document.parse(inputjson);
    }

    /**
     * @Author 
     * @Date 9:59 八月 24 0024
     * @Description: 將Document轉化成json(ObjectId以字串形式)字串,輸出。去掉了ObjectId,由"_id" : ObjectId("598d5bb7791c00bbf615977a")改成了:"_id":"598d5bb7791c00bbf615977a"
     */
    @Override
    protected void writeInternal(Document document, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> docmap = new HashMap<String, Object>(16);
        Iterator itdoc = document.entrySet().iterator();
        while (itdoc.hasNext()) {
            Document.Entry entry = (Document.Entry) itdoc.next();
            Object value = entry.getValue();
            if (value instanceof ObjectId) {
                value = value.toString();
            }
            docmap.put((String) entry.getKey(), value);
        }
        String out = mapper.writeValueAsString(docmap);
        System.out.println("writeInternal,78lines,out-->"+out);
        outputMessage.getBody().write(out.getBytes("UTF-8"));
    }
}

2.自定義ObjectId返序列化類ObjectIdDeserializer,繼承JsonDeserializer

public class ObjectIdDeserializer extends JsonDeserializer<ObjectId> {

    @Override
    public ObjectId deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonNode node = p.getCodec().readTree(p);
        String oid = node.get("_id").asText();
        System.out.println("反序列化:》"+oid);
        return new ObjectId(oid);
    }
}

3.配置spring檔案:

<mvc:annotation-driven>
   <mvc:message-converters register-defaults="false">  
       <!-- 增加自定義處理MongoDB 的Document 與 普通Json字串的轉換 -->
       <bean class="com.converter.DocumentHttpMessageConverter" />
   </mvc:message-converters>  
</mvc:annotation-driven>

這裡要特別注意下:
register-defaults=”false” 這個不用配置應該也可以,具體看專案