java @valid 密码不一致_一个成熟的Java项目如何优雅地处理异常

0a37425b98b54fe410fc090408267066.png

(一)概述

异常处理是一个系统最重要的环节,当一个项目变得很大的时候,异常处理和日志系统能让你快速定位到问题。对于用户或者接口调用者而言,优雅的异常处理可以让调用者快速知道问题所在。本文将介绍如何优雅地处理异常。

(二)使用通用的返回体

我们希望所有的错误都以Json的方式返回给客户,因此拿出上次写的通用返回体,新建一个类CommonResult记录返回体。

@Data@AllArgsConstructor@NoArgsConstructorpublic class CommonResult {    private int code;    private String message;    private Object data;}复制代码

新建一个枚举类ResponseCode集成code和message。

public enum ResponseCode {    // 系统模块    SUCCESS(0, "操作成功"),    ERROR(1, "操作失败"),    SERVER_ERROR(500, "服务器异常"),    // 通用模块 1xxxx    ILLEGAL_ARGUMENT(10000, "参数不合法"),    REPETITIVE_OPERATION(10001, "请勿重复操作"),    ACCESS_LIMIT(10002, "请求太频繁, 请稍后再试"),    MAIL_SEND_SUCCESS(10003, "邮件发送成功"),    // 用户模块 2xxxx    NEED_LOGIN(20001, "登录失效"),    USERNAME_OR_PASSWORD_EMPTY(20002, "用户名或密码不能为空"),    USERNAME_OR_PASSWORD_WRONG(20003, "用户名或密码错误"),    USER_NOT_EXISTS(20004, "用户不存在"),    WRONG_PASSWORD(20005, "密码错误"),    ;    ResponseCode(Integer code, String msg) {        this.code = code;        this.msg = msg;    }    private Integer code;    private String msg;    public Integer getCode() {        return code;    }    public void setCode(Integer code) {        this.code = code;    }    public String getMsg() {        return msg;    }    public void setMsg(String msg) {        this.msg = msg;    }}复制代码

(三)自定义运行时异常

自定义一个运行时异常类,构造方法传入异常参数即可。

public class MyException extends RuntimeException{    private String msg;    public MyException(String msg) {        super(msg);    }}复制代码

(四)编写一个统一的异常处理类

异常处理类是整个异常处理核心,SpringBoot中提供了ControllerAdvice注解来拦截异常,使用RestControllerAdvice注解保证了返回Json格式。

如果拦截到的异常属于MyException,则按Json格式返回错误结果。

@RestControllerAdvicepublic class ExceptionController {    @ResponseStatus(HttpStatus.BAD_REQUEST)    @ExceptionHandler(value = Exception.class)    public CommonResult exceptionHandler(Exception e){        //如果抛出的异常属于自定义异常,就以JSON格式返回        if (e instanceof MyException){            return new CommonResult(ResponseCode.ERROR.getCode(),ResponseCode.ERROR.getMsg(),"自定义的错误为:"+e.getMessage());        }        //如果都不是就打印出异常的信息        return new CommonResult(ResponseCode.ERROR.getCode(),ResponseCode.ERROR.getMsg(),"错误的信息为:"+e.getMessage());    }}复制代码

(五)测试

为了看初效果,这里手动抛出一个异常来测试,新建IndexController,手动抛出异常

@RestControllerpublic class IndexController {    @RequestMapping(value = "/index",method = RequestMethod.GET)    public String index(){        throw new MyException("测试");    }}复制代码

查看调用结果:

5c48934c734de401cbd88a4baaf1db47.png

(六)对实体类的校验

有这样一个场景,登陆注册时用户名和密码有长度限制,手机号有格式限制,如果不满足要求就无法注册。这个功能前端可以限制,但是对于后端接口而言,也需要进行限制,万一前端没有限制住呢。

导入两个校验依赖包:

javax.validation    validation-api    2.0.1.Finalorg.hibernate    hibernate-validator    6.1.0.Final复制代码

编写实体类,在每个属性上加上校验包的验证参数。

@Datapublic class Register {    @Length(max = 20,min = 4,message = "用户名长度需要在4到20个字符之间")    @NotBlank(message = "用户名不能为空")    private String username;    @NotBlank(message = "手机号不能为空")    @Pattern(regexp = "^1[3|4|5|8][0-9]d{8}$",message = "电话号码格式不正确")    private String phone;    @Length(max = 20,min = 4,message = "密码长度需要在4到20个字符之间")    @NotBlank(message = "密码不能为空")    private String password;}复制代码

我们在需要使用的方法中增加@Valid注解进行校验,比如这个post请求中我要校验。

@PostMapping("/register")public CommonResult register(@Valid @RequestBody Register register){    //一连串注册的业务    userService.registerUser(register);    return new CommonResult(ResponseCode.SUCCESS.getCode(),ResponseCode.SUCCESS.getMsg(),"");}复制代码

@Valid在校验失败的情况下会报出参数不合法的异常,还是在统一的异常处理类中捕获异常,如果是MethodArgumentNotValidException,就取出对应的message数据。

@RestControllerAdvicepublic class ExceptionController {    @ResponseStatus(HttpStatus.BAD_REQUEST)    @ExceptionHandler(value = Exception.class)    public CommonResult exceptionHandler(Exception e){        //如果属于参数校验异常,就抛出校验的错误        if (e instanceof MethodArgumentNotValidException){            MethodArgumentNotValidException methodArgumentNotValidException= (MethodArgumentNotValidException) e;            return new CommonResult(ResponseCode.ERROR.getCode(),ResponseCode.ERROR.getMsg(),                    "校验错误:"+methodArgumentNotValidException.getBindingResult().getFieldError().getDefaultMessage());        }//如果是自定义的异常,就给出具体的异常原因        else if (e instanceof MyException){            return new CommonResult(ResponseCode.ERROR.getCode(),ResponseCode.ERROR.getMsg(),"自定义的错误为:"+e.getMessage());        }        //如果都不是就打印出异常的信息        return new CommonResult(ResponseCode.ERROR.getCode(),ResponseCode.ERROR.getMsg(),"错误的信息为:"+e.getMessage());    }}复制代码

(七)测试校验

接下来就可以测试校验的功能了,通过postman访问

b00cd74e4d7b4077b4487625ae2babab.png

如果输入参数不满足之前的设置,就会给出具体的错误信息。而不是抛出让人无法接收的报错:

e93872376b7cf30975a5d678a8269499.png

(八)总结

许多人写代码时最不考虑的就是异常处理,简单地实现需求就好了,所以才会导致许多不可预估的bug出现。好了,本期文章就到这里了,我们下期再见。

看完三件事❤️

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  1. 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  2. 关注头条号 『 JAVA后端架构 』,不定期分享原创知识。
  3. 同时可以期待后续文章ing
  4. 关注作者后台私信【888】有惊喜相送
8d5f62fb06f508929573aa46d188cb73.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/551188.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spark消费kafka产生数据堆积怎么处理_SparkStreaming读取Kafka的两种方式

本文主要从以下几个方面介绍SparkStreaming读取Kafka的两种方式:一、SparkStreaming简介二、Kafka简介三、Redis简介(可用于保存历史数据或偏移量数据)四、SparkStreaming读取Kafka数据的两种方式 五、演示Demo一、SparkStreaming简介可以参考这篇文章:SparkStreami…

python字符串操作作业_python 第二天作业

#python 中的循环#先介绍for循环#格式#for 临时变量 in 可迭代对象# 循环体#name neusoft#for a in name :# print(a)# if a s# print(嘿嘿)#循环次数哪里去了?# #这个a是什么鬼? a是临时变量 提前声明 python自动为你创建#range (起始位置&#xff0c…

python 白化_Python新疆某气候要素IDW(反距离权重)插值

1、Rbf插值import numpy as npimport cartopy.crs as ccrsimport cartopy.feature as cfeatfrom cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTERfrom cartopy.io.shapereader import Readerimport matplotlib.pyplot as pltimport matplotlib.ticker a…

帆软报表参数传给网络报表_报表开发工具FineReport的使用: 程序网络报表

1定义程序网络报表程序网络报表所在类需要继承com.fr.web.reportlet这个抽象类,并且需要实现createReport(ReportletRequest arg0)这个方法,并返回报表对象。具体代码如下:2//程序网络报表package com.fr.demo; import java.util.Map;impo…

bootstrap 取消_学习写个网站(5)Bootstrap学习2

吃了2天烧烤夜宵&#xff0c;还是得讲点自律。【正文】继续bootstrap&#xff0c;还是菜鸟教程。11. 分页就是还有种就是翻页&#xff0c;12. 标签class"label label-default">默认标签</span>label-primarylabel-success13. 警告就是那种可以取消的消息&am…

jdbc mysql user_tab_comments_MySQL学习(五)——使用JDBC完成用户表CRUD的操作

通过案例我们发现“获得连接”和“释放资源”两次代码将在之后的增删改查所有功能中都存在&#xff0c;开发中遇到此种情况&#xff0c;将采用工具类的方法进行抽取&#xff0c;从而达到代码的重复利用。1、使用properties配置文件开发中获得连接的4个参数(驱动、URL、用户名、…

mysql中try的意思_java中try是什么意思

try是Java中的关键字&#xff0c;主要用于异常处理机制&#xff0c;那么它有什么作用呢&#xff1f;try – 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内&#xff0c;当try语句块内发生异常时&#xff0c;异常就被抛出。它一般与catch..finally组合使用块…

linux用java连接mysql_Java使用JDBC方式连接数据库

开发一个JDBC应用程序&#xff0c;基本需要以下几个步骤&#xff1a;1.把JDBC驱动类装载入Java虚拟机中。使用java.lang.Class类的静态方法forName(String className)实现。例&#xff1a; Class.forName("JDBC驱动类名称")2.加载驱动&#xff0c;并与数据库建立连接…

java web gradle_gradle学习之旅(四) 使用gradle构建简单的java web项目

本节通过一个简单的javaweb项目来体会gradle的使用需求构建一个javaweb项目&#xff0c;搭建jspservlet开发环境可以将需求分解为两步&#xff1a;使用gradle构建一个java项目为该项目构建web视图层工具gradle4.3ideajdk 1.8实验过程首先在idea中创建一个空的gradle项目创建如下…

java 整数 引用传递_关于Java引用传递的一个困惑?

Java的引用(包括基本类型&#xff0c;对象引用类型)在声明、方法调用等时候都会产生新的引用&#xff0c;复制等号右侧的引用。分为下面3种情况&#xff1a;基本类型代表的值存储在引用里面&#xff0c;引用中专门有个区域存储这个值&#xff0c;所以在复制的时候&#xff0c;值…

java fastjson 泛型_解决fastjson泛型转换报错的解决方法

错误信息Exception in thread "main" java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to com.xh.demo.UserDO泛性类Datapublic class ResultSetDTO {private Integer totalSize;private Integer count;private List records;}实体类…

通达OA header身份认证绕过漏洞复现

通达OA是中国通达公司的一套协同办公自动化软件&#xff0c;通达OA2013&#xff0c;通达OA2016&#xff0c;通达OA2017 存在身份认证绕过漏洞&#xff0c;攻击者可以利用漏洞生成cookie&#xff0c;实现未授权访问。 1.漏洞级别 高危 2.漏洞搜索 fofa title"office An…

leetcode mysql 排名_Leetcode178.分数排名(中等)

题目编写一个 SQL 查询来实现分数排名。如果两个分数相同&#xff0c;则两个分数排名(Rank)相同。请注意&#xff0c;平分后的下一个名次应该是下一个连续的整数值。换句话说&#xff0c;名次之间不应该有“间隔”。-----------| Id | Score |-----------| 1 | 3.50 || 2 | 3.6…

java post 中文乱码问题_java post中文乱码问题

java post中文乱码问题function addcategory() {if (document.myform.category.value "") {alert("商品分类不能为空");return;}//var categorydocument.getElementById("category").value;var c document.myform.category.value;alert(c);wit…

java struct工作原理_Struts2的工作原理(图解)详解

Struts2的工作原理上图来源于Struts2官方站点&#xff0c;是Struts 2 的整体结构。一个请求在Struts2框架中的处理大概分为以下几个步骤(可查看源码&#xff1a;https://github.com/apache/struts):1 客户端初始化一个指向Servlet容器(例如Tomcat)的请求2 这个请求经过一系列的…

java 旅行家的预算_洛谷 P1016 旅行家的预算 Java解法

洛谷 P1016 旅行家的预算 Java解法洛谷 P1016 旅行家的预算 Java解法package com.two;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);double D1 sc.nextDouble();// 两个城市之间的距离double C …

java语言执行过程_Java程序的运行过程(执行流程)分析

万事知其然&#xff0c;要知其所以然&#xff0c;所以本节带大家来详细了解一下 Java 程序的执行过程。从《使用记事本编写运行Java程序》一节的案例可以看出&#xff0c;Java 程序的运行必须经过编写、编译和运行 3 个步骤。编写&#xff1a;是指在 Java 开发环境中进行程序代…

php搭建云服务器,云服务器上如何搭建php环境

1) 安装libtool和libtool-ltdl[rootlocalhost mysql]# yum -y install "libtool*"[rootlocalhost mysql]# yum -y install "libtool-ltdl*"2) 手工修改gd库文件PHP 5.4 也有一些 Bug&#xff0c;在检测 gd 库时会报错&#xff0c;需要我们手工修改。命令如…

php实现文本替换,php 如何实现文字替换

php实现文字替换的方法&#xff1a;首先创建一个PHP示例文件&#xff1b;然后输入代码“str_replace("iwind", "kiki", "i love iwind, iwind said");”&#xff1b;最后输出执行结果即可。在php替换字符效率最高也是最简单字符替换函数str_repl…

php 删除指定html标签,php删除html标签的三种解决办法

分享下PHP删除HTMl标签的三种方法。方法1&#xff1a;直接取出想要取出的标记function strip($str){$strstr_replace("","",$str);//$strhtmlspecialchars($str);return strip_tags($str);}//edit by www.jbxue.com?>方法2.PHP 中有个 strip_tags 函数…