目录
前言
一. JSON概述
二. JSON数据返回
1. 导入pom依赖
2. 添加配置文件(spring-mvc.xml)
3. @ResponseBody注解使用
4. 效果展示
5. Jackson介绍
三. 全局异常处理
1. 为什么要全局异常处理
2. 异常处理思路
3. 异常处理方式一
4. 异常处理方式二
5. 异常处理方式三
前言
Spring MVC 在传递数据时,通常都需要对数据的类型和格式进行转换。而这些数据不仅可以是常见的 String 类型,还可以是 JSON 等其他类型。
JSON 是近些年一种比较流行的数据格式,它与 XML 相似,也是用来存储数据的。但相较于 XML,JSON 数据占用的空间更小,解析速度更快。因此,使用 JSON 数据进行前后台的数据交互也是一种十分常见的手段。
另外,在实际的应用开发中,经常会不可避免地遇到各种可预知的、不可预知的异常,此时我们就需要对这些异常处理,以保证程序正常运行。
本篇将对 Spring MVC 的 JSON 类型数据返回以及异常处理进行分享。
一. JSON概述
JSON(JavaScript Object Notation,JS 对象标记)是一种轻量级的数据交互格式。与 XML 一样,JSON 也是一种基于纯文本的数据格式。通过它,我们不仅能够传递 String、Number、Boolean 等简单类型的数据,还可以传递数组、Object 对象等复杂类型的数据。
二. JSON数据返回
Spring MVC 为我们提供了两个十分重要的与 JSON 格式转换相关的注解,它们分别是 @RequestBody 和 @ResponseBody。
注解 | 位置 | 说明 |
---|---|---|
@RequestBody | 方法的形参上 | 该注解用于将请求体中的数据绑定到控制器方法的形参上。 |
@ResponseBody | 方法上 | 该注解用于将控制器方法的返回值,直接作为响应报文的响应体响应到 浏览器上。 |
这里以 @ResponseBody为例
JSON 支持对象结构,数组结构,对象和数组组合成的复杂结构
1. 导入pom依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.3</version>
</dependency>
2. 添加配置文件(spring-mvc.xml)
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="mappingJackson2HttpMessageConverter"/>
</list>
</property>
</bean>
<bean id="mappingJackson2HttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<!--处理中文乱码以及避免IE执行AJAX时,返回JSON出现下载文件-->
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>text/json;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
3. @ResponseBody注解使用
@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<T>
* @param req
* @param clazz
* @return
*/
@ResponseBody
@RequestMapping("/list")
public List<clazz> list(HttpServletRequest req, clazz clazz){
PageBean pageBean = new PageBean();
pageBean.setRequest(req);
List<clazz> 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<clazz> lst = this.clazzBiz.listPager(clazz, null);
return lst.get(0);
}
return null;
}
/**
* 返回List<Map>
* @param req
* @param clazz
* @return
*/
@ResponseBody
@RequestMapping("/mapList")
public List<Map> mapList(HttpServletRequest req, clazz clazz){
PageBean pageBean = new PageBean();
pageBean.setRequest(req);
List<Map> lst = this.clazzBiz.mapListPager(clazz, pageBean);
return lst;
}
/**
* 返回Map
* @param req
* @param clazz
* @return
*/
@ResponseBody
@RequestMapping("/mapLoad")
public Map mapLoad(HttpServletRequest req, clazz clazz){
if(clazz.getCid() != null){
List<Map> lst = this.clazzBiz.mapListPager(clazz, null);
return lst.get(0);
}
return null;
}
@ResponseBody
@RequestMapping("/all")
public Map all(HttpServletRequest req, clazz clazz){
PageBean pageBean = new PageBean();
pageBean.setRequest(req);
List<clazz> 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<Map> mapListPager(clazz clazz, PageBean pageBean);
@Override
public List<Map> mapListPager(clazz clazz, PageBean pageBean) {
return clazzMapper.mapListPager(cl
mapper接口
List<Map> mapListPager(clazz clazz);
sql映射文件
<select id="mapListPager" resultType="java.util.Map" parameterType="com.xissl.model.clazz" >
select
<include refid="Base_Column_List" />
from t_struts_class
<where>
<if test="cname != null">
and cname like concat('%',#{cname},'%')
</if>
</where>
</select>
4. 效果展示
对象结构
JSON 的对象结构以“{”开始,以“}”结束,中间则由 0 个或多个以英文的逗号(即“,”)分隔的 key/value 对构成。(实体或集合T/map)
数组结构
JSON 的数组结构以“[”开始、以“]”结束,中间部分由 0 个或多个以英文的逗号(即“,”)分隔的值列表组成。(List<T>/List<map>)
混合结构
JSON数据返回第一种方式是在方法上添加@ResponseBody注解。
除此之外还可以将@ResponseBody注解放于类上。
以及第三种方式,将@Controller与@ResponseBody合并,即@RestController
5. Jackson介绍
Jackson是一个简单基于Java应用库,Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。Jackson所依赖的jar包较少,简单易用并且性能也要相对高些,并且Jackson社区相对比较活跃,更新速度也比较快。
特点
-
容易使用,提供了高层次外观,简化常用的用例。
-
无需创建映射,API提供了默认的映射大部分对象序列化。
-
性能高,快速,低内存占用
-
创建干净的json
-
不依赖其他库
-
代码开源
常用注解
注解 | 说明 |
---|---|
@JsonIgnore | 作用在字段或方法上,用来完全忽略被注解的字段和方法对应的属性 |
@JsonProperty | 作用在字段或方法上,用来对属性的序列化/反序列化,可以用来避免遗漏属性,同时提供对属性名称重命名 |
@JsonIgnoreProperties | 作用在类上,用来说明有些属性在序列化/反序列化时需要忽略掉 |
@JsonUnwrapped | 作用在属性字段或方法上,用来将子JSON对象的属性添加到封闭的JSON对象 |
@JsonFormat | 指定序列化日期/时间值时的格式 |
三. 全局异常处理
1. 为什么要全局异常处理
我们知道,系统中异常包括:编译时异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。在开发中,不管是dao层、service层还是controller层,都有可能抛出异常,在springmvc中,能将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护。
2. 异常处理思路
系统的dao、service、controller出现异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。
3. 异常处理方式一
SpringMVC中自带了一个异常处理器叫SimpleMappingExceptionResolver,该处理器实现了HandlerExceptionResolver 接口,全局异常处理器都需要实现该接口。
在配置文件(spring-mvc.xml)中添加异常处理器
<!-- springmvc提供的简单异常处理器 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 定义默认的异常处理页面 -->
<property name="defaultErrorView" value="error"/>
<!-- 定义异常处理页面用来获取异常信息的变量名,也可不定义,默认名为exception -->
<property name="exceptionAttribute" value="ex"/>
<!-- 定义需要特殊处理的异常,这是重要点 -->
<property name="exceptionMappings">
<props>
<prop key="java.lang.RuntimeException">error</prop>
</props>
<!-- 还可以定义其他的自定义异常 -->
</property>
</bean>
添加一个异常代码
@ResponseBody
@RequestMapping("/list")
public List<clazz> list(HttpServletRequest req, clazz clazz){
PageBean pageBean = new PageBean();
pageBean.setRequest(req);
List<clazz> lst = this.clazzBiz.listPager(clazz, pageBean);
System.out.println(1 / 0);
return lst;
}
异常处理界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
出错咯......
${ex}
</body>
</html>
测试效果:
4. 异常处理方式二
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" %>
<html>
<head>
<title>Title</title>
</head>
<body>
出错咯......
${ex}
<br>
${msg}
</body>
</html>
5. 异常处理方式三
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界面的异常信息