目录
Spring MVC 在传递数据时,通常都需要对数据的类型和格式进行转换。而这些数据不仅可以是常见的 String 类型,还可以是 JSON 等其他类型。
JSON 是近些年一种比较流行的数据格式,它与 XML 相似,也是用来存储数据的。但相较于 XML,JSON 数据占用的空间更小,解析速度更快。因此,使用 JSON 数据进行前后台的数据交互也是一种十分常见的手段。
另外,在实际的应用开发中,经常会不可避免地遇到各种可预知的、不可预知的异常,此时我们就需要对这些异常处理,以保证程序正常运行。
本篇将对 Spring MVC 的 JSON 类型数据返回以及异常处理进行分享。
JSON(JavaScript Object Notation,JS 对象标记)是一种轻量级的数据交互格式。与 XML 一样,JSON 也是一种基于纯文本的数据格式。通过它,我们不仅能够传递 String、Number、Boolean 等简单类型的数据,还可以传递数组、Object 对象等复杂类型的数据。
Spring MVC 为我们提供了两个十分重要的与 JSON 格式转换相关的注解,它们分别是 @RequestBody 和 @ResponseBody。
| 注解 | 位置 | 说明 |
|---|---|---|
| @RequestBody | 方法的形参上 | 该注解用于将请求体中的数据绑定到控制器方法的形参上。 |
| @ResponseBody | 方法上 | 该注解用于将控制器方法的返回值,直接作为响应报文的响应体响应到 浏览器上。 |
这里以 @ResponseBody为例
JSON 支持对象结构,数组结构,对象和数组组合成的复杂结构
-
com.fasterxml.jackson.core -
jackson-databind -
2.9.3 -
com.fasterxml.jackson.core -
jackson-core -
2.9.3 -
com.fasterxml.jackson.core -
jackson-annotations -
2.9.3 -
"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> -
"messageConverters"> -
-
-
"mappingJackson2HttpMessageConverter" - class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
-
-
"supportedMediaTypes"> -
-
text/html;charset=UTF-8 -
text/json;charset=UTF-8 -
application/json;charset=UTF-8 -
-
@ResponseBody注解的作用是将Controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据。
注意:在使用此注解之后不会再走视图解析器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。
controller层
- package com.xissl.web;
-
- import com.xissl.biz.clazzBiz;
- import com.xissl.model.clazz;
- import com.xissl.utils.PageBean;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.ResponseBody;
-
- import javax.servlet.http.HttpServletRequest;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
-
- @Controller
- @RequestMapping("/clz/json")
- public class JsonController {
- @Autowired
- private clazzBiz clazzBiz;
-
- /**
- * 返回List
- * @param req
- * @param clazz
- * @return
- */
- @ResponseBody
- @RequestMapping("/list")
- public List
list(HttpServletRequest req, clazz clazz){ - PageBean pageBean = new PageBean();
- pageBean.setRequest(req);
- List
lst = this.clazzBiz.listPager(clazz, pageBean); - return lst;
- }
-
- /**
- * 返回T
- * @param req
- * @param clazz
- * @return
- */
- @ResponseBody
- @RequestMapping("/load")
- public clazz load(HttpServletRequest req, clazz clazz){
- if(clazz.getCid() != null){
- List
lst = this.clazzBiz.listPager(clazz, null); - return lst.get(0);
- }
- return null;
- }
-
-
- /**
- * 返回List
- * @param req
- * @param clazz
- * @return
- */
- @ResponseBody
- @RequestMapping("/mapList")
- public List
- PageBean pageBean = new PageBean();
- pageBean.setRequest(req);
- List
- return lst;
- }
-
- /**
- * 返回Map
- * @param req
- * @param clazz
- * @return
- */
- @ResponseBody
- @RequestMapping("/mapLoad")
- public Map mapLoad(HttpServletRequest req, clazz clazz){
- if(clazz.getCid() != null){
- List
- return lst.get(0);
- }
- return null;
- }
-
-
- @ResponseBody
- @RequestMapping("/all")
- public Map all(HttpServletRequest req, clazz clazz){
- PageBean pageBean = new PageBean();
- pageBean.setRequest(req);
- List
lst = this.clazzBiz.listPager(clazz, pageBean); - Map map = new HashMap();
- map.put("lst",lst);
- map.put("pageBean",pageBean);
- return map;
- }
-
- @ResponseBody
- @RequestMapping("/jsonStr")
- public String jsonStr(HttpServletRequest req, clazz clazz){
- return "clzEdit";
- }
-
-
- }
业务逻辑层
List
- @Override
- public List
- return clazzMapper.mapListPager(cl
mapper接口
List
sql映射文件
-
- select
-
"Base_Column_List" /> - from t_struts_class
-
- <if test="cname != null">
- and cname like concat('%',#{cname},'%')
- if>
-
-
对象结构
JSON 的对象结构以“{”开始,以“}”结束,中间则由 0 个或多个以英文的逗号(即“,”)分隔的 key/value 对构成。(实体或集合T/map)

数组结构
JSON 的数组结构以“[”开始、以“]”结束,中间部分由 0 个或多个以英文的逗号(即“,”)分隔的值列表组成。(List

混合结构

JSON数据返回第一种方式是在方法上添加@ResponseBody注解。
除此之外还可以将@ResponseBody注解放于类上。
以及第三种方式,将@Controller与@ResponseBody合并,即@RestController
Jackson是一个简单基于Java应用库,Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。Jackson所依赖的jar包较少,简单易用并且性能也要相对高些,并且Jackson社区相对比较活跃,更新速度也比较快。
特点
容易使用,提供了高层次外观,简化常用的用例。
无需创建映射,API提供了默认的映射大部分对象序列化。
性能高,快速,低内存占用
创建干净的json
不依赖其他库
代码开源
常用注解
| 注解 | 说明 |
|---|---|
| @JsonIgnore | 作用在字段或方法上,用来完全忽略被注解的字段和方法对应的属性 |
| @JsonProperty | 作用在字段或方法上,用来对属性的序列化/反序列化,可以用来避免遗漏属性,同时提供对属性名称重命名 |
| @JsonIgnoreProperties | 作用在类上,用来说明有些属性在序列化/反序列化时需要忽略掉 |
| @JsonUnwrapped | 作用在属性字段或方法上,用来将子JSON对象的属性添加到封闭的JSON对象 |
| @JsonFormat | 指定序列化日期/时间值时的格式 |
我们知道,系统中异常包括:编译时异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。在开发中,不管是dao层、service层还是controller层,都有可能抛出异常,在springmvc中,能将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护。
系统的dao、service、controller出现异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。

SpringMVC中自带了一个异常处理器叫SimpleMappingExceptionResolver,该处理器实现了HandlerExceptionResolver 接口,全局异常处理器都需要实现该接口。
在配置文件(spring-mvc.xml)中添加异常处理器
-
-
"org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> -
-
"defaultErrorView" value="error"/> -
-
"exceptionAttribute" value="ex"/> -
-
"exceptionMappings"> -
-
"java.lang.RuntimeException">error -
-
-
-
添加一个异常代码
- @ResponseBody
- @RequestMapping("/list")
- public List
list(HttpServletRequest req, clazz clazz){ - PageBean pageBean = new PageBean();
- pageBean.setRequest(req);
- List
lst = this.clazzBiz.listPager(clazz, pageBean); - System.out.println(1 / 0);
- return lst;
- }
异常处理界面
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
-
Title - 出错咯......
- ${ex}
测试效果:

- package com.xissl.exception;
-
- public class GlobalException extends RuntimeException {
- public GlobalException() {
- }
-
- public GlobalException(String message) {
- super(message);
- }
-
- public GlobalException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public GlobalException(Throwable cause) {
- super(cause);
- }
-
- public GlobalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
- super(message, cause, enableSuppression, writableStackTrace);
- }
- }
1.通过instanceof判断异常类型
2.通过设置mv.setView(new MappingJackson2JsonView())方式返回JSON数据
- package com.xissl.component;
-
- import com.xissl.exception.GlobalException;
- import org.springframework.stereotype.Component;
- import org.springframework.web.servlet.HandlerExceptionResolver;
- import org.springframework.web.servlet.ModelAndView;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- @Component
- public class GlobalExceptionHandler implements HandlerExceptionResolver {
- @Override
- public ModelAndView resolveException(HttpServletRequest httpServletRequest,
- HttpServletResponse httpServletResponse,
- Object o, Exception e) {
- ModelAndView mv = new ModelAndView();
- mv.setViewName("error");
- if (e instanceof GlobalException){
- GlobalException globalException = (GlobalException) e;
- mv.addObject("ex",globalException.getMessage());
- mv.addObject("msg","全局异常....");
- }else if (e instanceof RuntimeException){
- RuntimeException runtimeException = (RuntimeException) e;
- mv.addObject("ex",runtimeException.getMessage());
- mv.addObject("msg","运行时异常....");
- }else {
- mv.addObject("ex",e.getMessage());
- mv.addObject("msg","其它异常....");
- }
- return mv;
- }
- }
- @ResponseBody
- @RequestMapping("/jsonStr")
- public String jsonStr(HttpServletRequest req, clazz clazz){
- if(true)
- throw new GlobalException("又出错咯......");
- return "clzEdit";
- }
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
-
Title - 出错咯......
- ${ex}
- ${msg}
- package com.xissl.component;
-
- import com.xissl.exception.GlobalException;
- import org.springframework.web.bind.annotation.ControllerAdvice;
- import org.springframework.web.bind.annotation.ExceptionHandler;
- import org.springframework.web.bind.annotation.ResponseBody;
-
- import java.util.HashMap;
- import java.util.Map;
-
- @ControllerAdvice
- public class GlobalExceptionResolver {
-
-
- // 返回错误json数据
- @ResponseBody
- @ExceptionHandler
- public Map handler(Exception e){
- Map map = new HashMap();
- if (e instanceof GlobalException){
- GlobalException globalException = (GlobalException) e;
- map.put("ex",globalException.getMessage());
- map.put("msg","全局异常....");
- }else if (e instanceof RuntimeException){
- RuntimeException runtimeException = (RuntimeException) e;
- map.put("ex",runtimeException.getMessage());
- map.put("msg","运行时异常....");
- }else {
- map.put("ex",e.getMessage());
- map.put("msg","其它异常....");
- }
- return map;
- }
- }
这段代码运行后展示的效果是JSON形式的异常信息
- package com.xissl.component;
-
- import com.xissl.exception.GlobalException;
- import org.springframework.web.bind.annotation.ControllerAdvice;
- import org.springframework.web.bind.annotation.ExceptionHandler;
- import org.springframework.web.bind.annotation.ResponseBody;
- import org.springframework.web.servlet.ModelAndView;
-
- import java.util.HashMap;
- import java.util.Map;
-
- @ControllerAdvice
- public class GlobalExceptionResolver {
-
- // 跳转错误页面
- @ExceptionHandler
- public ModelAndView handler(Exception e){
- ModelAndView mv = new ModelAndView();
- mv.setViewName("error");
- if (e instanceof GlobalException){
- GlobalException globalException = (GlobalException) e;
- mv.addObject("ex",globalException.getMessage());
- mv.addObject("msg","全局异常....");
- }else if (e instanceof RuntimeException){
- RuntimeException runtimeException = (RuntimeException) e;
- mv.addObject("ex",runtimeException.getMessage());
- mv.addObject("msg","运行时异常....");
- }
- return mv;
- }
-
-
- }
这段代码运行后展示的效果是jsp界面的异常信息