SpringMVC

来源:互联网 发布:进货收货出售软件 编辑:程序博客网 时间:2024/06/06 00:35

在项目开发中,不可避免遇到后台返回json的情况。今天学习两类后台返回 json的方式。


【1】返回自定义json

测试代码如下:

@RequestMapping(value="deviceInfo",produces = "application/json; charset=utf-8")@ResponseBody//这里用到了阿里巴巴的fastjson,同样你可以使用其他json框架public String testJson(){        JSONObject jsonObject = new JSONObject();        jsonObject.put("code","true");        jsonObject.put("message","操作成功");        return jsonObject.toJSONString();}

该种方式优点是,可以自定义返回json对象,使用比较方便。


【2】使用HttpMessageConverter<T>

加入jackjson的jar,注意你的spring版本。这里使用的是Spring4.3.4,不支持jackjson2.8:

这里写图片描述

测试代码依赖代码:

....    private static Map<Integer, Employee> employees = null;    @Autowired    private DepartmentDao departmentDao;    static{        employees = new HashMap<Integer, Employee>();        employees.put(1001, new Employee(1001, "E-AA", "aa@163.com", 1, new Department(101, "D-AA")));        employees.put(1002, new Employee(1002, "E-BB", "bb@163.com", 1, new Department(102, "D-BB")));        employees.put(1003, new Employee(1003, "E-CC", "cc@163.com", 0, new Department(103, "D-CC")));        employees.put(1004, new Employee(1004, "E-DD", "dd@163.com", 0, new Department(104, "D-DD")));        employees.put(1005, new Employee(1005, "E-EE", "ee@163.com", 1, new Department(105, "D-EE")));    }public Collection<Employee> getAll(){        return employees.values();    }....

真正测试代码:

    @ResponseBody    @RequestMapping("/testJson")    public Collection<Employee> testJson(){        return employeeDao.getAll();    }

不用拼接,直接返回employeeDao.getAll(); 这是一个集合,元素类型为Employee!!!


分析其实现原理,首先了解HttpMessageConverter<T>

其是Spring3.0新添加的一个接口,负责将请求信息转换为一个对象(类型为T),将对象(类型为T)输出为响应信息

    • 接口如下:
/* * Copyright 2002-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.springframework.http.converter;import java.io.IOException;import java.util.List;import org.springframework.http.HttpInputMessage;import org.springframework.http.HttpOutputMessage;import org.springframework.http.MediaType;/** * Strategy interface that specifies a converter that can convert from and to HTTP requests and responses. * * @author Arjen Poutsma * @author Juergen Hoeller * @since 3.0 */public interface HttpMessageConverter<T> {    /**     * Indicates whether the given class can be read by this converter.     * @param clazz the class to test for readability     * @param mediaType the media type to read, can be {@code null} if not specified.     * Typically the value of a {@code Content-Type} header.     * @return {@code true} if readable; {@code false} otherwise     */     /*指定转换器可以读取的对象类型,即转换器是否可将请求信息转换为clazz类型的对象,同时指定支持MIME类型(text/html,application/json等)     */    boolean canRead(Class<?> clazz, MediaType mediaType);    /**     * Indicates whether the given class can be written by this converter.     * @param clazz the class to test for writability     * @param mediaType the media type to write, can be {@code null} if not specified.     * Typically the value of an {@code Accept} header.     * @return {@code true} if writable; {@code false} otherwise     */     /*指定转换器是否可将clazz类型的对象写到响应流中,响应流支持的媒体类型在MediaType中定义     */    boolean canWrite(Class<?> clazz, MediaType mediaType);    /**     * Return the list of {@link MediaType} objects supported by this converter.     * @return the list of supported media types     */     /*该转换器支持的媒体类型     */    List<MediaType> getSupportedMediaTypes();    /**     * Read an object of the given type form the given input message, and returns it.     * @param clazz the type of object to return. This type must have previously been passed to the     * {@link #canRead canRead} method of this interface, which must have returned {@code true}.     * @param inputMessage the HTTP input message to read from     * @return the converted object     * @throws IOException in case of I/O errors     * @throws HttpMessageNotReadableException in case of conversion errors     */     /*将请求信息流转换为T类型的对象     */    T read(Class<? extends T> clazz, HttpInputMessage inputMessage)            throws IOException, HttpMessageNotReadableException;    /**     * Write an given object to the given output message.     * @param t the object to write to the output message. The type of this object must have previously been     * passed to the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}.     * @param contentType the content type to use when writing. May be {@code null} to indicate that the     * default content type of the converter must be used. If not {@code null}, this media type must have     * previously been passed to the {@link #canWrite canWrite} method of this interface, which must have     * returned {@code true}.     * @param outputMessage the message to write to     * @throws IOException in case of I/O errors     * @throws HttpMessageNotWritableException in case of conversion errors     */     /*将T类型的对象写到响应流中,同时指定响应的媒体类型为contentType     */    void write(T t, MediaType contentType, HttpOutputMessage outputMessage)            throws IOException, HttpMessageNotWritableException;}

【运行流程如下图所示:】

这里写图片描述

HttpInputMessage 接口:

    • 把请求体转换为input stream;
public interface HttpInputMessage extends HttpMessage {    /**     * Return the body of the message as an input stream.     * @return the input stream body (never {@code null})     * @throws IOException in case of I/O Errors     */    InputStream getBody() throws IOException;}

HttpOutputMessage 接口:

    • 把消息体转换为output stream返回。
public interface HttpOutputMessage extends HttpMessage {    /**     * Return the body of the message as an output stream.     * @return the output stream body (never {@code null})     * @throws IOException in case of I/O Errors     */    OutputStream getBody() throws IOException;}

【其实现类如下图所示:】

这里写图片描述

常用实现类功能说明如下:

① StringHttpMessageConverter:将请求信息转换为字符串;

② ByteArrayHttpMessageConverter:读写二进制数据;

③ SourceHttpMessageConverter:读写javax.xml.transform.Source类型的数据;

④ FormHttpMessageConverter : 将表单数据读取到MultiValueMap中;

⑤ ResourceHttpMessageConverter:读写org.springframework.core.io.Resource对象;

⑥ BufferedImageHttpMessageConverter:读写BufferedImage对象;

⑦ MappingJackson2HttpMessageConverter:利用jackson开源包的objectMapper读写JSON数据。


DispatcherServlet默认装配有三个HandlerAdapter:

这里写图片描述

而RequestMappingHanlerAdapter默认装配HttpMessageConverter如下:

这里写图片描述

加入jackjson包后,HttpMessageConverter如下

这里写图片描述

多了一个MappingJacksonHttpMessageConverter!!!

它,就是将响应对象转换为JSON返回给页面的!!


使用HttpMessageConverter<T>将请求信息转化并绑定到处理方法的入参中;或将响应结果转换为对应类型的响应信息,Spring提供了两种途径:

① 使用@RequestBody/@ResponseBody对处理方法进行标注;

② 使用HttpEntity<T> / ResponseEntity<T>作为处理方法的入参或返回值;

当控制器处理方法使用到了① 或② 时,Spring首先根据请求头或响应头的Accept属性选择匹配的HttpMessageConverter,进而根据参数类型和泛型类型的过滤得到匹配的HttpMessageConverter。

若找不到可用的HttpMessageConverter,将报错。

代码示例如下图所示:

这里写图片描述

1 0