统一结果集和异常处理

统一结果集和异常处理

查询参数的接收

HTTP请求:

URL/URI:

统一资源标识符(Uniform Resource Identifier,URI)是一个用于标识某一互联网资源名称的字符串。

URL 的全称为 Universal Resource Locator

URI >= URL

比如:

  • /users:URI,
  • http://localhost:8989/users :URL 或者URI

请求参数:

  • 查询参数:/users?id = 1 & userName=Rose
  • 路径参数:/users/1/Rose

对于Rest接口,比较推荐使用路径参数。

SpringMVC中的Controller的方法,默认接收的查询参数,如果你要接收路径参数,必须加@PathVariable注解。

路径参数如果参数名不一致:

在这里插入图片描述

查询参数,默认无需额外处理,是默认的。但如果参数名不一致,也需要加个注解@RequestParam

举例:使用查询参数根据id查询用户:

  /**
     * 查询参数示例
     * @param id
     * @return
     */
    @GetMapping("/user/query")
//    public User getById2(Integer id){
    public User getById2(@RequestParam("id") Integer id){
        System.out.println(id);

        User user1 =new User();
        user1.setId(id);
        user1.setUserName("Rose");
        user1.setAge(18);

        return user1;
    }

浏览器请求:

http://localhost:8989/user/query?id=123

资源路径冲突

如果资源路径重复,将会报异常,程序无法启动:

在代码中发现:
这里应改成/userdemo

映射对:

key:value

资源路径:controller方法

如果启动失败,则除了控制台异常,没有停止按钮。

在这里插入图片描述

统一结果集

现在存在的问题:

  • 接口返回的结果不统一,前端不好处理,一般我们都返回json
  • 数据格式太简单,不适合业务.

企业中一般的格式:

{
    结果码:20000,
    提示消息:"用户名或密码不正确",
    数据:{
    	id:1,
        userName:Rose
    }
}

我们需要在Java中定义统一结果集对象类:

package cn.bobohost.market.pojo;

import lombok.Data;

/**
 * 统一结果集对象
 * Dta:数据传输/转换对象
 */
@Data
public class ResultDto<T> {
    /**
     * 响应的数据状态码
     * 20000 : 表示本次请求一切正常,响应也正常
     * 50000 : 本次操作出现的错误(具体错误信息需要有针对性的返回给前端)
     *      用户名或密码错误
     *      没有任何员工数据
     *      根据员工id删除账号失败
     */
    private Integer code = 20000;

    /**
     * 每个状态对应的本次操作的描述信息
     * 20000 :操作成功
     * 50000 :操作失败
     */
    private String msg ;

    /**
     * 本次请求返回给客户端的数据
     */
    private T data;


    /**
     *  封装分页相关信息
     */
    private Integer pages;
    private Long total;


    //无参构造器(默认自带)
    public ResultDto() {
    }
    //有参构造器(自定)
    public ResultDto(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    /**
     * 调用成功之后的结果
     * @param msg
     * @param data
     * @return
     * @param <T>
     */
    public static  <T> ResultDto<T> success(String msg,T data) {
        return new ResultDto<>(20000,msg,data);
    }

    /**
     * 失败的结果
     * @param code
     * @param msg
     * @return
     * @param <T>
     */
    public static  <T> ResultDto<T> error(Integer code,String msg) {
        return new ResultDto<>(code,msg,null);
    }

    /**
     * 自定义结果
     * @param code
     * @param msg
     * @param data
     * @return
     * @param <T>
     */
    public static  <T> ResultDto<T> of(Integer code, String msg, T data) {
        return new ResultDto<>(code,msg,data);
    }

}

将UserController复制一份UserDemoController,编写代码:

package cn.bobohost.market.web.controller;

import cn.bobohost.market.pojo.ResultDto;
import cn.bobohost.market.pojo.User;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 * 用户的Controller
 */
@RestController
//请求映射:如果放到类上,那么将来请求的时候,规则:类上的这个路径+方法上的路径。因此我们可以抽取前缀,一般不同模块有不同前缀
@RequestMapping("/userdemo")
public class UserDemoController {

    /**
     * 所有Controller的路径不能重复
     * @param user
     * @return
     */
    @PostMapping
    public ResultDto add(@RequestBody User user){
        //服务端控制台打印
        System.out.println(user);
        //返回结果给客户端
        return ResultDto.success("保存成功",null);
    }

    /**
     * 更新用户
     * @param user 用来封装数据的消息体
     * @param id 用户的唯一编号
     * @return
     */
    @PutMapping("/{id}")
    public ResultDto update(@RequestBody User user,@PathVariable Integer id){
        //服务端控制台打印
        System.out.println(user);
        //返回结果给客户端
        return ResultDto.success("修改成功",null);
    }

    /**
     * 删除
     * 客户端:/user/1
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    public ResultDto remove(@PathVariable Integer id){
        System.out.println(id);
        //返回结果给客户端
        return ResultDto.success("删除成功",null);
    }

    /**
     * 查询所有的用户列表
     * @return
     */
    @GetMapping
    public ResultDto list(){
        List<User> userList =new ArrayList<>();
        //添加元素---自己模拟两个用户
        User user1 =new User();
        user1.setId(1);
        user1.setUserName("Rose");
        user1.setAge(18);

        User user2 =new User();
        user2.setId(2);
        user2.setUserName("Jack");
        user2.setAge(88);

        //将用户添加到列表
        userList.add(user1);
        userList.add(user2);

        //返回列表
        return ResultDto.success("查询成功",userList);
    }


    /**
     * 根据id查询一个用户
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public ResultDto getById(@PathVariable Integer id){
        System.out.println(id);

        User user1 =new User();
        user1.setId(id);
        user1.setUserName("Rose");
        user1.setAge(18);

        return ResultDto.success("查询成功",user1);
    }


}

由于ResultDTO是通用的,因此我们可以放到common包中,拖动重构:

在这里插入图片描述

重构之后:

在这里插入图片描述

统一分页结果类:

package cn.bobohost.market.common.pojo;

import lombok.Data;

import java.util.List;

/**
 * 分页返回结果
 */
@Data
public class ResultPageDto<T> {

    private Long total;//总记录数
    private List<T> rows;//当前页的数据列表

    public ResultPageDto(Long total, List<T> rows) {
        this.total = total;
        this.rows = rows;
    }

    public static <T> ResultPageDto<T> of(Long total, List<T> rows){
        return new ResultPageDto(total,  rows);
    }

}

Java的异常

Java语言的健壮性的机制,会导致操作终止。

表面现象上看,是出错了了效果。实际上,异常不是错误,很多时候是我们主动抛出来。

当程序出现意外或者主动的异常时,控制台会打印很多字符,描述异常的信息和发生异常的代码的位置。

Java的异常体系:
在这里插入图片描述

在idea中要想找任何东西(类、代码、方法、idea的功能),可以连续按三下shift键:

比如找maven的配置:

在这里插入图片描述

找throwable类:

在这里插入图片描述

throwable类是异常的祖宗,代表了所有异常。

error异常类:一般是虚拟机使用的,系统级别的异常(cpu问题、内存不足),一般不用。

Exception:普通异常,我们业务上会用的

RuntimeException:运行时异常,代码在运行时发生的异常。继承了Exception,功能更强大,一般我们用这个。

一旦出现异常的时候,我们要拦截处理这个异常,如果不处理,则会抛到控制台打印。

回到业务:

在操作数据的时候一定会成功吗?不是!

什么原因造成失败?代码有问题、数据库问题

下面以查所有的为例:

制造除零异常:

在这里插入图片描述

作为程序员,至少会调试代码。

比如这里,可以点击异常提示的行,直接跳转到某行。
在这里插入图片描述

第二种方式,主动抛出异常:

处理异常

业务中,可能会发生不可预测的异常以及自定义抛出的异常。

如果发生了异常,则当前操作会终止,比如启动的时候抛异常,启动就失败了;如果启动成功,但发请求的时候异常了,那么当前请求失败了。

默认情况下,当操作发生异常时,控制台会打印异常,并且SpringMVC会用默认的方式处理异常,返回响应给客户端。

  /**
     * 查询所有的用户列表
     * @return
     */
    @GetMapping
    public ResultDto list(){



        //主动制造异常:
        // 1)触发jdk内置的异常
//        int d =1/0;

        //2) 主动抛出异常
        //欺骗了编译器
//        if(true){
//            throw new RuntimeException("我主动制造的异常");
//        }


        //捕捉处理异常:try如果有异常,就抓取;
        //try是用来捕获
        try {
            List<User> userList =new ArrayList<>();
            //添加元素---自己模拟两个用户
            User user1 =new User();
            user1.setId(1);
            user1.setUserName("Rose");
            user1.setAge(18);

            User user2 =new User();
            user2.setId(2);
            user2.setUserName("Jack");
            user2.setAge(88);

            //将用户添加到列表
            userList.add(user1);
            userList.add(user2);
            //制造异常
//            int d =1/0;
             if(true){
            throw new RuntimeException("我主动制造的异常");
        }
            //返回列表
            return ResultDto.success("查询成功",userList);
         //catch是用来抓取特定异常,可以处理.异常只能抓同样的或比自己辈分小的异常。
//        }catch (ArithmeticException e){
        }catch (Exception e){
            System.out.println("出现了异常:"+e.getMessage());
            return ResultDto.error(50000,"查询失败");
        }

        //返回列表
//        return ResultDto.success("查询成功",userList);
    }

统一异常处理

我们每一个方法都自己处理异常,非常麻烦。是否可以统一处理异常,简化代码呢?

可以!

机制:AOP(面向切面的编程):不改变原来代码就可以增强原来的代码。

SpringMVC帮咱提供了AOP的功能机制,可以实现AOP。我们利用这个东东,来实现统一异常处理。

我们可以编写一个通知(增强)类,来统一处理异常:

在这里插入图片描述

ControllerExceptionAdvice

package cn.bobohost.market.web.advice;

import cn.bobohost.market.common.pojo.ResultDto;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 用来处理Controller里面的异常的增强类
 * RestControllerAdvice:专门用来处理拦截contrller中的异常的类
 */
@RestControllerAdvice
public class ControllerExceptionAdvice {

    /**
     * 方法名随便
     * @ExceptionHandler默认处理所有异常,会将异常对象扔到方法的参数中
     * @param e
     * @return
     */
    @ExceptionHandler
    public ResultDto handleThrowable(Throwable e){
        //记录日志(也可以发邮件、发短信等)
//        log.error(e.getMessage(),e);
        System.out.println("操作失败,错误是:"+e.getMessage());
        //返回响应结果
        return ResultDto.error(50000,"操作失败!");
    }

}

面的异常的增强类

  • RestControllerAdvice:专门用来处理拦截contrller中的异常的类
    */
    @RestControllerAdvice
    public class ControllerExceptionAdvice {

    /**

    • 方法名随便
    • @ExceptionHandler默认处理所有异常,会将异常对象扔到方法的参数中
    • @param e
    • @return
      */
      @ExceptionHandler
      public ResultDto handleThrowable(Throwable e){
      //记录日志(也可以发邮件、发短信等)
      // log.error(e.getMessage(),e);
      System.out.println(“操作失败,错误是:”+e.getMessage());
      //返回响应结果
      return ResultDto.error(50000,“操作失败!”);
      }

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值