Fork me on GitHub

SpringMVC接口返回json、上传及下载文件

以前做过用Struts2的接口,跟springmvc的不完全相同,同样都是需要注解,只不过另外一些配置的地方不同就是了。那么接下来就是正文了。

返回json

不管是返回json,还是在upload和download类中会用到很多httpservlet类,故需要在project structure中选中libraries选项,添加新的Java library,目录为tomcat/lib/servlet-api.jar。

返回单个数据

首先要配置pom.xml,添加spring4和Jackson的依赖

<properties>
    <spring.version>4.3.16.RELEASE</spring.version>
    <jackson.version>2.9.5</jackson.version>
</properties>

<dependencies>
    <!--Spring 4 dependencies-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!-- Jackson JSON Mapper -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>${jackson.version}</version>
    </dependency>
  </dependencies>

在servlet文件中添加配置如下:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"
          p:ignoreDefaultModelOnRedirect="true">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
            </list>
        </property>
</bean>

配置完后写一个student类:

public class User {

    String name;
    String age;

    public User(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

新建一个JsonController类:

    @RequestMapping(value = "/test",method = RequestMethod.GET)
    @ResponseBody public User test(){
        User user=new User("QingMi","18");
        return user;
    }

完成,运行:

注:如果发生报”No converter found for return value of type”错误,则有可能是以下几个原因:
1、检查Jackson依赖是否正确添加
2、servlet是否添加正确配置
3、model类是否存在getter/setter方法(我的就是这个错误)

哦,对了,再吐槽一句,国内博客清一色的前两个方法,只有Stack Overflow里第二个答案提到了这一点。可能大家的敲代码习惯比较好吧。

返回多个数据

在JsonController中添加如下方法:

    @RequestMapping(value = "/testList",method = RequestMethod.GET)
    @ResponseBody public Map<String,Object> testList(){
        User user1=new User("QingMi","21");
        User user2=new User("Yuner","25");
        List<User> list=new ArrayList<>();
        list.add(user1);
        list.add(user2);
        Map<String,Object> modelMap=new HashMap<>();
        modelMap.put("School","杭电");
        modelMap.put("list",list);
        return modelMap;
    }

运行:

上传文件

上传下载文件也需要先配置一下,先在pom.xml中添加库:

    <!-- 文件上传下载依赖 -->
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.5</version>
    </dependency>
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.2</version>
    </dependency>

在servlet文件中配置一下:

    <!-- 文件上传的配置 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
        p:defaultEncoding="UTF-8">
        <!-- 指定所上传文件的总大小不能超过5000KB。注意maxUploadSize属性的限制不是针对单个文件,而是所有文件的容量之和 -->
        <property name="maxUploadSize" value="5000000"/>
    </bean>

    <!-- 该异常是SpringMVC在检查上传的文件信息时抛出来的,而且此时还没有进入到Controller方法中 -->
    <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <!-- 遇到MaxUploadSizeExceededException异常时,自动跳转到WebContent目录下的error.jsp页面 -->
                <prop key="org.springframework.web.multipart.MaxUploadSizeExceededException">error</prop>
            </props>
        </property>
    </bean>

在index.jsp所在的目录下新建一个upload.jsp文件:

<form action="/upload" method="post" enctype="multipart/form-data">
    文件1:<input type="file" name="file"><br/>
    <input type="submit" value="上传">
</form>

新建一个UploadController类,里面添加如下方法:

@RequestMapping(value = "/upload",method = RequestMethod.POST,produces = "application/json;charset=utf-8")
    @ResponseBody public String uplaod(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws Exception{
        if(!file.isEmpty()){
             //此处basePath可获取到项目的根目录路径
            String basePath = request.getSession().getServletContext().getRealPath("/upload")+File.separator;
            if(!new File(basePath).exists()){
                new File(basePath).mkdirs();
            }
            file.transferTo(new File(basePath+file.getOriginalFilename()));
            return "upload success and name is "+file.getOriginalFilename();
        }
        return "upload fail and the name is "+file.getOriginalFilename();
    }

运行如下:



上面有好几个处理中文乱码的地方我放最后说一下:
1、upload.jsp页面要用utf-8编码
2、servlet里,在配置multipartResolver时,也要配置defaultEncoding为UTF-8编码

这两个配置就可以解决文件上传及保存时的中文名不发生问题。但有时我喜欢把关键处理的问题部分放在外面看看处理好没有,所以在Controller的注解里,我加了这一个属性:

produces = “application/json;charset=utf-8”

这样就可以解决return返回的name为一串问号的问题,正常显示为中文了。其实解决这个问题一共有三个方法,我只是放了一个最简单的解决办法上来。详情请见这里

下载文件

新建一个download.jsp文件,主体部分代码如下:

<body>
<a href="download?fileName=ym.jpg">download</a>
</body>

在新建一个DownloadController类:

@Controller
public class DownloadController {
    //下载指定图片
    @RequestMapping(value = "/download")
    public String download(String fileName, HttpServletRequest request, HttpServletResponse response){
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition","attachment:fileName="+fileName);
        try {
            String path="F:/upload/";
            InputStream inputStream=new FileInputStream(new File(path+fileName));
            OutputStream os=response.getOutputStream();
            byte[] b=new byte[2048];
            int length;
            while ((length=inputStream.read(b))>0){
                os.write(b,0,length);
            }
            os.close();
            inputStream.close();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

其中,在attachment后面可以设置下载文件所显示的文件名。
哦对了,在写博客的时候才发现下载文件时没处理文件名中文名字乱码的问题,上传文件则不用担心这个问题。解决办法是对fileName做一些处理:

"attachment:fileName="+ URLEncoder.encode(fileName,"utf-8")

下载文件的”ym.jpg”也改为”杨幂.jpg”,同时放置一张图片。
运行:

OK,暂时就是这样了,若是以后项目有新的接口处理需求,再来更新。

-------------本文结束感谢您的阅读-------------