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…

MySQL数据步骤管控_数据管理的发展过程分为哪三个阶段

数据管理的发展过程分为哪三个阶段发布时间:2020-11-12 12:01:00来源:亿速云阅读:124作者:小新这篇文章主要介绍数据管理的发展过程分为哪三个阶段,文中介绍的非常详细,具有一定的参考价值,感兴…

myftpadmin+proftpd+mysql架设ftp服务器_linux下用Proftpd搭建ftp服务器及配置方法

首先proftpd是一个开源软件,其官方地址是http://www.proftpd.org,目前最高版本是:1.3.1(非稳定版),稳定的版本是1.3.0,下载文件为proftpd-1.3.0a.tar.gz我下载的是1.3.0,上传到服务器上后按照常规的方法安装…

mysql设置输出格式_rsyslog 配置mysql输出格式

http://www.rsyslog.com/doc/v8-stable/configuration/modules/ommysql.html文档中:Note rsyslog contains a canned default template to write to the MySQL database. It works on the MonitorWare schema. This template is:$template tpl,”insert into System…

nginx trac mysql svn_apache+mysql+trac+svn

Windows 2008 R2安装ApacheSVNTracMySQL步骤及心得一、软件准备1.Apache_2.2.14-win32-x86-no_ssl.msi2.Setup-Subversion-1.7.1.exe3.TortoiseSVN-1.6.16.215114.Mysql-5.5.28-win32.exehttp://www.doczj.com/doc/3bbc3a4b915f804d2b16c1e7.html Framework V4.06.Python-2.7.6…

python 所有关键字解释_Python关键字详细解释

Python关键字,也被称为保留字。保留字是官方定义的,具有特殊含义的单词。 用户不能使用保留字作为变量、函数、类等自定义的名称。查看当前Python版本保留字的方法。打开cmd,执行python,进入到Python交互模式中然后依次输入下面的…

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字符串迭代/函数

我需要我的“items”变量将每个项目打印到新行上。我总是在“items”中得到总数,在“total”中得到总数。“总计”打印出我想要的结果,但我希望这些项目单独打印。在有什么想法?在def adding_report():user_input input("Report Types …

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系统属性_mysql 显示表字段及mysql系统信息

SHOW DATABASES //列出 MySQL Server 数据库。SHOW TABLES [FROM db_name] //列出数据库数据表。SHOW TABLE STATUS [FROM db_name] //列出数据表及表状态信息。SHOW COLUMNS FROM tbl_name [FROM db_name] …

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

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

如何在命令中授权给MySQL_MySQL如何使用授权命令grant

本文实例&#xff0c;运行于 MySQL 5.0 及以上版本。MySQL 赋予用户权限命令的简单格式可概括为&#xff1a;grant 权限 on 数据库对象 to 用户一、grant 普通数据用户&#xff0c;查询、插入、更新、删除 数据库中所有表数据的权利。grant select on testdb.* to common_user%…

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

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

mysql 字段钳口可加引号_根据处理对象划分,计算机可以分为模拟计算机、(

【判断题】( )3.保证数控机床各运动部件间的良好润滑就能提高机床寿命。【单选题】在储位编码中,把一些相关性货品经过集合以后,区分成几个品项群,再对其进行编码的方法是( )。【填空题】在数据库技术中,DBMS是 ,DB是指() 、DBS是指数据库系统。【单选题】25. 为保证下刀的安全…

mysql存储过程游标移动_mysql动态游标与mysql存储过程游标(示例)

-- 建立测试表和数据create table webuser (username varchar(10));insert into webuser values (a1),(a2),(a3),(b1),(b2),(b3);commit;-- 建立存储过程drop procedure if exists dynamic_cursor;delimiter // www.jbxue.comCREATE PROCEDURE dynamic_cursor (IN p_name varch…

python ftplib bufsize_python:ftplib模块

from ftplib import FTP #加载ftp模块ftpFTP() #设置变量ftp.set_debuglevel(2) #打开调试级别2&#xff0c;显示详细信息ftp.set_pasv(0) #0主动模式 1 #被动模式ftp.connect("IP","port") #连接的ftp s…

python程序设计实验教程_Python程序设计实验教程

第1章 主教材各章节概要1.1 Python概述概要1.1.1 Python简介1.1.2 Python开发环境1.1.3 Python程序示例1.2 Python基础知识概要1.2.1 程序的书写规范1.2.2 标识符和关键字1.2.3 Python的数值类型、常量与变量1.2.4 Python的字符串类型1.2.5 数据类型判断和数据类型间转换1.2.6 …