• SpringMVC之JSON数据返回&异常处理机制


    目录

    前言

    一、JSON数据返回

    1.导入依赖

    2.配置spring-mvc.xml

    3.使用@ResponseBody注解

    4.Jackson

    4.1.介绍

    4.2.常用注解

    二、异常处理机制

    1.为什么要全局异常处理

    2.异常处理思路

    3.SpringMVC异常分类

    4.综合案例

    4.1.异常处理方式一

    4.2.异常处理方式二

    4.3异常处理方式三

    5.响应封装类


    前言

            Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过一套注解,我们可以快速的搭建一个Web应用。在本文中,我们将重点介绍如何在Spring MVC中返回JSON数据以及如何处理异常。

    一、JSON数据返回

    1.导入依赖

    为了使@ResponseBody注解生效,我们需要配置一个Jackson消息转换器,用于将Java对象序列化为JSON字符串。需要在pom.xml文件中添加Jackson依赖:

    1. <dependency>
    2. <groupId>com.fasterxml.jackson.coregroupId>
    3. <artifactId>jackson-databindartifactId>
    4. <version>2.9.3version>
    5. dependency>
    6. <dependency>
    7. <groupId>com.fasterxml.jackson.coregroupId>
    8. <artifactId>jackson-coreartifactId>
    9. <version>2.9.3version>
    10. dependency>
    11. <dependency>
    12. <groupId>com.fasterxml.jackson.coregroupId>
    13. <artifactId>jackson-annotationsartifactId>
    14. <version>2.9.3version>
    15. dependency>

    2.配置spring-mvc.xml

    1. <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    2. <property name="messageConverters">
    3. <list>
    4. <ref bean="mappingJackson2HttpMessageConverter"/>
    5. list>
    6. property>
    7. bean>
    8. <bean id="mappingJackson2HttpMessageConverter"
    9. class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    10. <property name="supportedMediaTypes">
    11. <list>
    12. <value>text/html;charset=UTF-8value>
    13. <value>text/json;charset=UTF-8value>
    14. <value>application/json;charset=UTF-8value>
    15. list>
    16. property>
    17. bean>

    3.使用@ResponseBody注解

            在SpringMVC中,我们可以使用@ResponseBody注解将Controller方法的返回值直接转换为JSON格式。这样,当客户端请求该方法时,将会收到一个JSON格式的响应。

    1. package com.ctb.controller;
    2. import com.ctb.biz.UserBiz;
    3. import com.ctb.model.User;
    4. import com.ctb.utils.PageBean;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.stereotype.Controller;
    7. import org.springframework.web.bind.annotation.RequestMapping;
    8. import org.springframework.web.bind.annotation.ResponseBody;
    9. import javax.servlet.http.HttpServletRequest;
    10. import java.util.HashMap;
    11. import java.util.List;
    12. import java.util.Map;
    13. @Controller
    14. @RequestMapping("/user/json")
    15. public class JsonController {
    16. @Autowired
    17. private UserBiz userBiz;
    18. /**
    19. * 返回List<T> JSON数组
    20. * @param req
    21. * @param user
    22. * @return
    23. */
    24. @ResponseBody
    25. @RequestMapping("/list")
    26. public List<User> list(HttpServletRequest req, User user){
    27. PageBean pageBean = new PageBean();
    28. pageBean.setRequest(req);
    29. List<User> lst = this.userBiz.listPager(user, pageBean);
    30. System.out.println(1 / 0);
    31. return lst;
    32. }
    33. /**
    34. * 返回T JSON对象
    35. * @param req
    36. * @param user
    37. * @return
    38. */
    39. @ResponseBody
    40. @RequestMapping("/load")
    41. public User load(HttpServletRequest req, User user){
    42. if(user.getId() != null){
    43. List<User> lst = this.userBiz.listPager(user, null);
    44. return lst.get(0);
    45. }
    46. return null;
    47. }
    48. /**
    49. * 返回List<Map> JSON数组
    50. * @param req
    51. * @param user
    52. * @return
    53. */
    54. @ResponseBody
    55. @RequestMapping("/mapList")
    56. public List<Map> mapList(HttpServletRequest req, User user){
    57. PageBean pageBean = new PageBean();
    58. pageBean.setRequest(req);
    59. List<Map> lst = this.userBiz.mapListPager(user, pageBean);
    60. return lst;
    61. }
    62. /**
    63. * 返回Map JSON对象
    64. * @param req
    65. * @param user
    66. * @return
    67. */
    68. @ResponseBody
    69. @RequestMapping("/mapLoad")
    70. public Map mapLoad(HttpServletRequest req, User user){
    71. if(user.getId() != null){
    72. List<Map> lst = this.userBiz.mapListPager(user, null);
    73. return lst.get(0);
    74. }
    75. return null;
    76. }
    77. //混合
    78. @ResponseBody
    79. @RequestMapping("/all")
    80. public Map all(HttpServletRequest req, User user){
    81. PageBean pageBean = new PageBean();
    82. pageBean.setRequest(req);
    83. List<User> lst = this.userBiz.listPager(user, pageBean);
    84. Map map = new HashMap();
    85. map.put("lst",lst);
    86. map.put("pageBean",pageBean);
    87. return map;
    88. }
    89. @ResponseBody//
    90. @RequestMapping("/jsonStr")
    91. public String jsonStr(HttpServletRequest req, User user){
    92. return "userEdit";
    93. }
    94. }

    注意:在使用此注解之后不会再走视图解析器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。分别为对象,数组,对象数组(混合)

     以下是部分方法运行结果

    4.Jackson

    4.1.介绍

    Jackson是一个简单基于Java应用库,Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。Jackson所依赖的jar包较少,简单易用并且性能也要相对高些,并且Jackson社区相对比较活跃,更新速度也比较快。

    特点

    • 容易使用,提供了高层次外观,简化常用的用例。

    • 无需创建映射,API提供了默认的映射大部分对象序列化。

    • 性能高,快速,低内存占用

    • 创建干净的json

    • 不依赖其他库

    • 代码开源

    4.2.常用注解
    注解说明
    @JsonIgnore作用在字段或方法上,用来完全忽略被注解的字段和方法对应的属性
    @JsonProperty作用在字段或方法上,用来对属性的序列化/反序列化,可以用来避免遗漏属性,同时提供对属性名称重命名
    @JsonIgnoreProperties作用在类上,用来说明有些属性在序列化/反序列化时需要忽略掉
    @JsonUnwrapped作用在属性字段或方法上,用来将子JSON对象的属性添加到封闭的JSON对象
    @JsonFormat指定序列化日期/时间值时的格式

    二、异常处理机制

    1.为什么要全局异常处理

    我们知道,系统中异常包括:编译时异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。在开发中,不管是dao层、service层还是controller层,都有可能抛出异常,在springmvc中,能将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护。

    2.异常处理思路

    系统的dao、service、controller出现异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。

    3.SpringMVC异常分类

    • 使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver;

    • 实现Spring的异常处理接口HandlerExceptionResolver自定义自己的异常处理器;

    • 使用@ControllerAdvice + @ExceptionHandler

    4.综合案例

    4.1.异常处理方式一

    SpringMVC中自带了一个异常处理器叫SimpleMappingExceptionResolver,该处理器实现了HandlerExceptionResolver 接口,全局异常处理器都需要实现该接口。

    1. <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    2. <property name="defaultErrorView" value="error"/>
    3. <property name="exceptionAttribute" value="ex"/>
    4. <property name="exceptionMappings">
    5. <props>
    6. <prop key="java.lang.RuntimeException">errorprop>
    7. props>
    8. property>
    9. bean>

    注:页面跳转由SpringMVC来接管了,所以此处的定义默认的异常处理页面都应该配置成逻辑视图名。  

    前端页面

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4. <title>错误界面title>
    5. head>
    6. <body>
    7. 错误信息界面。。。。。。
    8. ${ex}
    9. body>
    10. html>

    4.2.异常处理方式二
    •  创建一个名为GlobalException的自定义异常类

    这是一个名为GlobalException的Java类,它继承自RuntimeExceptionRuntimeException是Java中所有未检查异常的父类。这个类提供了多种构造方法,用于创建不同类型的异常对象。

    1. package com.ctb.exception;
    2. public class GlobalException extends RuntimeException {
    3. // 默认构造方法,创建一个不带任何消息和原因的运行时异常
    4. public GlobalException() {
    5. }
    6. // 带一个字符串消息的构造方法,创建一个带有指定消息的运行时异常
    7. public GlobalException(String message) {
    8. super(message);
    9. }
    10. // 带一个字符串消息和一个原因的构造方法,创建一个带有指定消息和原因的运行时异常
    11. public GlobalException(String message, Throwable cause) {
    12. super(message, cause);
    13. }
    14. // 带一个原因的构造方法,创建一个带有指定原因的运行时异常
    15. public GlobalException(Throwable cause) {
    16. super(cause);
    17. }
    18. // 带一个字符串消息、一个原因、一个标志位(是否抑制异常)和一个标志位(是否可写栈轨迹)的构造方法,创建一个带有指定消息、原因、抑制标志位和可写栈轨迹的运行时异常
    19. public GlobalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
    20. super(message, cause, enableSuppression, writableStackTrace);
    21. }
    22. }
    • 创建一个名为GlobalExceptionHandler的类,并实现了HandlerExceptionResolver接口。
    1. package com.ctb.component;
    2. import com.ctb.exception.GlobalException;
    3. import org.springframework.stereotype.Component;
    4. import org.springframework.web.servlet.HandlerExceptionResolver;
    5. import org.springframework.web.servlet.ModelAndView;
    6. import javax.servlet.http.HttpServletRequest;
    7. import javax.servlet.http.HttpServletResponse;
    8. @Component
    9. public class GlobalExceptionHandler implements HandlerExceptionResolver {
    10. @Override
    11. public ModelAndView resolveException(HttpServletRequest httpServletRequest,
    12. HttpServletResponse httpServletResponse,
    13. Object o, Exception e) {
    14. ModelAndView mv = new ModelAndView();
    15. mv.setViewName("error");//error.jsp
    16. if (e instanceof GlobalException){
    17. GlobalException globalException = (GlobalException) e;
    18. mv.addObject("ex",globalException.getMessage());
    19. mv.addObject("msg","全局异常....");
    20. }else if (e instanceof RuntimeException){
    21. RuntimeException runtimeException = (RuntimeException) e;
    22. mv.addObject("ex",runtimeException.getMessage());
    23. mv.addObject("msg","运行时异常....");
    24. }
    25. return mv;
    26. }
    27. }

    它实现了HandlerExceptionResolver接口(异常处理解析器)。当应用程序中抛出异常时,这个处理器会被调用,返回一个ModelAndView对象,用于渲染错误页面。

    代码解析:

    1. @Component注解表示这个类是一个Spring组件,Spring会自动扫描并管理这个类的实例。

    2. GlobalExceptionHandler类实现了HandlerExceptionResolver接口,该接口只有一个方法resolveException,Spring在处理异常时会调用这个方法。

    3. resolveException方法接收四个参数,分别是HttpServletRequest、HttpServletResponse、Object和Exception。HttpServletRequest和HttpServletResponse是HTTP请求和响应的对象,Object是当前处理的请求或响应的对象,Exception是发生的异常。

    4. resolveException方法中,首先创建了一个ModelAndView对象mv,然后设置了视图名称为"error",即错误页面。

    5. 接着判断异常的类型,如果是GlobalException类型,则获取其消息并添加到mv中,同时添加一条"全局异常...."的消息。如果是RuntimeException类型,则获取其消息并添加到mv中,同时添加一条"运行时异常...."的消息。

    6. 最后返回mv对象,Spring会根据这个对象渲染错误页面。

    部分方法测试 

    4.3异常处理方式三
    • ControllerAdvice:这是一个全局的异常处理器,可以捕获所有控制器中抛出的异常。通常我们会使用 @ControllerAdvice 注解来标记一个类为 ControllerAdvice,然后在该类中定义异常处理方法。

    • @ExceptionHandler:这是一个用于处理方法参数中抛出的指定类型的异常的注解。我们可以在方法上使用 @ExceptionHandler 注解来指定要处理的异常类型,以及处理方法的名称。

    1. package com.ctb.component;
    2. import com.ctb.exception.GlobalException;
    3. import org.springframework.web.bind.annotation.ControllerAdvice;
    4. import org.springframework.web.bind.annotation.ExceptionHandler;
    5. import org.springframework.web.bind.annotation.ResponseBody;
    6. import java.util.HashMap;
    7. import java.util.Map;
    8. @ControllerAdvice
    9. public class GlobalExceptionResolver {
    10. // 跳转错误页面
    11. // @ExceptionHandler
    12. // public ModelAndView handler(Exception e){
    13. // ModelAndView mv = new ModelAndView();
    14. // mv.setViewName("error");
    15. // if (e instanceof GlobalException){
    16. // GlobalException globalException = (GlobalException) e;
    17. // mv.addObject("ex",globalException.getMessage());
    18. // mv.addObject("msg","全局异常....");
    19. // }else if (e instanceof RuntimeException){
    20. // RuntimeException runtimeException = (RuntimeException) e;
    21. // mv.addObject("ex",runtimeException.getMessage());
    22. // mv.addObject("msg","运行时异常....");
    23. // }
    24. // return mv;
    25. // }
    26. // 返回错误json数据
    27. @ResponseBody
    28. @ExceptionHandler
    29. public Map handler(Exception e){
    30. Map map = new HashMap();
    31. if (e instanceof GlobalException){
    32. GlobalException globalException = (GlobalException) e;
    33. map.put("ex",globalException.getMessage());
    34. map.put("msg","全局异常....");
    35. }else if (e instanceof RuntimeException){
    36. RuntimeException runtimeException = (RuntimeException) e;
    37. map.put("ex",runtimeException.getMessage());
    38. map.put("msg","运行时异常....");
    39. }else {
    40. map.put("ex",e.getMessage());
    41. map.put("msg","其它异常....");
    42. }
    43. return map;
    44. }
    45. }

    代码解析

    handler(Exception e)方法:

    • 使用@ResponseBody注解,表示将返回的对象作为响应体发送给客户端。
    • 使用@ExceptionHandler注解,表示该方法用于处理控制器中抛出的异常。
    • 创建一个HashMap对象,用于存储异常信息。
    • 判断异常类型,如果是GlobalException,则将异常信息添加到map中,并设置提示信息为"全局异常....";
    • 如果异常类型是RuntimeException,则将异常信息添加到map中,并设置提示信息为"运行时异常....";
    • 其他类型的异常,将异常信息添加到map中,并设置提示信息为"其它异常....";
    • 返回map对象。

    部分方法测试 

     

     

    5.响应封装类

    • 创建自定义异常类BusinessException

    BusinessException自定义异常类将继承RuntimeException异常,该异常类用于处理在程序代码运行过程所产生的运行时业务异常信息。

    • 创建响应枚举类JsonResponseStatus

    JsonResponseStatus响应枚举类用于自定义错误码。

    • 创建响应封装类JsonResponseBody

    JsonResponseBody响应封装类用于以JSON的形式统一输出错误信息。

    1. // 响应封装类
    2. @ResponseBody
    3. @ExceptionHandler
    4. public R handler(Exception e){
    5. if (e instanceof GlobalException){
    6. GlobalException globalException = (GlobalException) e;
    7. return R.ok(666,"全局异常....",globalException.getMessage());
    8. }else if (e instanceof RuntimeException){
    9. RuntimeException runtimeException = (RuntimeException) e;
    10. return R.ok(666,"运行异常....",runtimeException.getMessage());
    11. }else {
    12. return R.ok(666,"其它异常....",e.getMessage());
    13. }
    14. }

    根据传入的异常对象进行类型判断,并返回相应的响应结果。

    部分方法测试

     

     

     

  • 相关阅读:
    C++知识精讲14 | 算法篇之二分查找算法
    HTML5期末考核大作业,网站——旅游景点。 学生旅行 游玩 主题住宿网页
    Vue - 图片浏览组件v-viewer
    Redis详解(一)
    数据驱动智能制造业务转型与创新
    【密码学补充知识】
    vue解决Not allowed to load local resource
    不愧是阿里内部 Spring Boot 笔记,从头到尾不讲废话
    Spring中获取bean的方式
    Java实现拼图游戏
  • 原文地址:https://blog.csdn.net/weixin_74268571/article/details/132855513