qiuxuhui

导航

Spring 使用Postman实现 mvc 与 Json数据交互 与 统一异常处理

一:使用Postman实现 mvc 与 Json数据交互

 

修改web.xml

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>


  <!--  三、编码过滤器-->
  <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>utf-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!--  一、spring mvc-->
  <servlet>
    <servlet-name>app1</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-web.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>app1</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

  

加入spring-web.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 1.组件扫描-->
    <context:component-scan base-package="com.cc.mvc.**"></context:component-scan>
    <!-- 2、注解适配器和映射器-->
    <mvc:annotation-driven/>
    <!--3、视图解析器-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <!-- 4、文件上传解析器-->
    <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 设置上传文件的最大尺寸为5MB -->
        <property name="maxUploadSize">
            <value>5242880</value>
        </property>
    </bean>

    <!--    5、静态资源映射
            mapping : 客户端浏览器路径  images/1.jpg   images/product/2.jpg
            location: 项目根据路径的下的指定目录下   /WEB-INF/images/1.jpg  /WEB-INF/images/2.jpg
    -->
    <mvc:resources mapping="/images/**" location="/WEB-INF/images/"></mvc:resources>

</beans>

  

建立User实体类

public class User {
    private String id;
    @JsonIgnore
    private String name;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

  

建立一个ResopsonseStatus枚举类,用来传递响应的结果

package com.cc.mvc.constants;

public enum ResopsonseStatus {

    OK("200","请求成功!"),
    AUTHOR_ERROR("1001","接口认证失败"),
    INTENAL_ERROR("1003","程序内部错误"),
    AUTHOR_OUTTIME("1002","认证过期");

    private String code;
    private String msg;

    ResopsonseStatus(String code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

  

建立ServerResponse实体类,用于反回响应后的结果

package com.cc.mvc.response;

import com.cc.mvc.constants.ResopsonseStatus;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.io.Serializable;

@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
//@JsonInclude(JsonInclude.Include.NON_NULL)
public class ServerResponse<T> implements Serializable{
    @JsonIgnore
    private String code;/*业务响应嘛*/
    @JsonIgnore
    private String msg;/*相应的信息*/
//    private Object obj;/*相应的数据,不推荐*/

    private T data;/*相应数据,推荐*/

    private ServerResponse(String code,String msg,T data) {

        this.code=code;
        this.msg=msg;
        this.data=data;

    }
    /*成功的响应*/
    public static ServerResponse ok(Object t){
        return new ServerResponse(ResopsonseStatus.OK.getCode(),ResopsonseStatus.OK.getMsg(),t);
    }
    /*失败的响应,固定错误信息*/
    public static ServerResponse error(Object t){
        return new ServerResponse(ResopsonseStatus.INTENAL_ERROR.getCode(), ResopsonseStatus.INTENAL_ERROR.getMsg(),t);
    }

    /*失败的响应,自定义错误信息*/
    public static ServerResponse errorMsg(String msg){
        return new ServerResponse(ResopsonseStatus.INTENAL_ERROR.getCode(), msg,null);
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

  注意:这里@JsonIgnore 是代表着,你需要显示到前端的就不加这个注解,不需要显示到前端的就加上这个注解

 

写Controller测试,这是使用json对象字符串的方式传递过去,我们运行一下,先将Tomcat跑起来

@Controller
public class TestController {

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/test", produces="application/json;charset=UTF-8")
    @ResponseBody
    public String test(HttpServletResponse response){

//        response.setContentType("application/json;charset=gbk");
        //return "index";
        return "{\"name\":\"二狗子\",\"age\":12,\"sex\":\"男\",\"address\":\"马栏山\"}";
    }
}

  

随后我们将Postman启动,并模拟前端发送请求到后台,获取返回值

 

接下来使用json对象数组的方式传递过去,在Controller加入测试方法

@RequestMapping("/json2")
    @ResponseBody  //spring mvc默认采用json序列化框架:fastJson ,Gson  , Jackson框架(默认)
    public User getUser(){
        User user = new User();
        user.setId("2");
        user.setName("二狗子");
        return user;
    }

  

在Postman里更改成下面这样,然后访问

 

 

 

这个User对象就返回过来了。但是name没返回过来,原因就是在建立User实体类表中加入了@JsonIgnore,所有才只显示了一个id过来,去掉就一起返回了

 

使用Postman模拟前端输入用户ID账号,并返回用户id到前端,在Controller加入测试方法

@ResponseBody
    @RequestMapping(value = "/add_user",method = RequestMethod.POST)
    public ServerResponse<User> addUser(@RequestBody User user){

        System.out.println("----进入adduser----"+user);


        return ServerResponse.ok(user);
    }

  

使用Postman访问

 

 

 注意这里一定要加上这个Content-Type

 

 

 

 二,实现统一异常处理

web开发的三层架构,既:web层,service层,dao层
每一层都可能抛出我们自己定义业务异常:登录异常,请求异常,认证失败异常,如果在每一层
去处理处理这些异常,这个代码冗余,可用性不高,入侵到业务代码。spring mvc中可以对异常
进行统一处理:

    DispatchServlet(老大)

      web层 ----往spring mvc抛

      service层 ---往web层抛出

      dao层 --往service抛出

  

spring mvc如何进行统一异常处理:日志记录,发短信/发邮件,返回一些友好并安全信息给前端。

 

第一方式:HandlerExceptionResolver 异常处理器

  1)返回值只能是ModelAndView  不适合前后端分离的项目,不推荐

package com.cc.mvc.exception;


/*
* 自定义异常处理器
*
* */

import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
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 MyHandlerExceptionResolver implements HandlerExceptionResolver{


    @Nullable
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, @Nullable Object o, Exception e) {
        ModelAndView mv = new ModelAndView();
        System.out.println("---MyHandlerExceptionResolver---"+e);
        mv.setViewName("error");

        return mv;
    }
}

  方式二:@ControllerAdvice  + @HandlerException  代理模式来解决(推荐)

    1)可以返回ModelAndView也可以返回Json字符串

  写入自定义异常类

package com.cc.mvc.exception;


import com.cc.mvc.response.ServerResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class MyExceptionAdvice {

    @ExceptionHandler
    @ResponseBody
    public ServerResponse handlerOrderException(OrderException e){
        System.out.println("----下订单过程中出错了...handlerOrderException---");
        /*
        * 1,写日志
        * 2,发送短信给开发人员
        * 3,发送邮件通知其他部门负责人
        * */
        return ServerResponse.error("订单异常,msg"+e.toString());
    }

    @ExceptionHandler(ArithmeticException.class)
    @ResponseBody
    public ServerResponse handlerArithException(ArithmeticException e){
        System.out.println("----程序内部中出错了...handlerArithException---");
        /*
        * 1,写日志
        * 2,发送短信给开发人员
        * 3,发送邮件通知其他部门负责人
        * */
        return ServerResponse.error("非业务异常:"+e.getMessage());
    }

}

  写入第二个自定义异常类

package com.cc.mvc.exception;

public class OrderException extends RuntimeException {


    public OrderException(String messges){

        super(messges);
    }
}

 

  写入UserService接口

package com.cc.mvc.service;

public interface UserService {

    void testEx() throws Exception;

}

  实现实体类中的方法

package com.cc.mvc.service.impl;

import com.cc.mvc.service.UserService;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {


    @Override
    public void testEx() throws Exception {
        int a =10/0;
    }
}

在Controller中加入测试方法

@RequestMapping("/exception01")
    @ResponseBody
    public String exception01(int num) throws Exception{

        if (num==2){
            throw new OrderException("订单出错");
        }else if(num ==1){
            int a =10/0;
        }

        userService.testEx();
        //业务处理
        return "success";
    }

  结果为下:

 

 

 

 

 

这里显示的只要不是等于2,就是非业务异常,如果需要修改等于2的订单异常返回的信息,可以在后台加上订单的枚举类

package com.cc.mvc.constants;

public enum OrderStatus {

//跟上面自定义枚举类一样的
}

  

posted on 2020-12-26 14:20  qiuxuhui  阅读(181)  评论(2编辑  收藏  举报