Java开发工具

相关插件

Alibaba Java Coding Guidelines

image.png
这是一个代码审查工具,能够对Java代码进行实时检测,包括不限于是否符合javadoc注解格式、各类命名规范、方法名驼峰要求、以及静态final字段下划线大写等。

不符合规范的用法及命名将会用高亮或下划线展示。
image.pngimage.png
该插件审查均符合阿里巴巴代码规约中的各项要求,可放心大胆使用。

EasyYapi

image.png
这是一个基于javadoc&KDoc&ScalaDoc规范并将编写的controller接口自动化生成接口文档,推送到yapi平台的管理工具。
下载插件后,打开设置,选择其他设置->EasyApi
image.png
将我们需要发布的yapi地址填入
image.png
转到controller层,右键任意位置,选择EasyApi->Export Yapi
image.png
将token输入到输入框中,点击确定即可一键发布到Yapi中。
image.png
token可到,yapi设置->token配置中找到
image.png

Mevan Helper

分析和解决pom冲突依赖关系的插件。
image.png
如图,标记出了mybatis-spring-boot-starter与mybatis的冲突。

好用的代码

Mybatis Code Generator

这是mybatis mapper、po、*mapper.xml的自动生成工具

<!-- MyBatis Generator -->
<dependency>
  <groupId>org.mybatis.generator</groupId>
  <artifactId>mybatis-generator-core</artifactId>
  <version>1.4.2</version>
</dependency>

配置MybatisPlugin插件


/**
 * Mybatis Generator拓展插件
 *
 * @author xxxxxx
 * @since 2024/7/28
 */
public class MybatisPlugin extends PluginAdapter {

    public static final DateTimeFormatter DATE_STANDARD_FORMAT = DateTimeFormatter.ofPattern("yyyy/MM/dd");
    public static final String AUTHOR = "mybatis generator";

    /**
     * 查询结果映射到的ResultMap中需要忽视的列
     */
    public static final List<String> RESULT_MAP_IGNORED = Lists.newArrayList("create_time", "update_time", "is_delete");

    /**
     * 是否设置逻辑删除
     */
    private static final Boolean TOMBSTONE = true;

    /**
     * 逻辑删除字段名,设置了逻辑删除时会调用
     */
    private static final String TOMBSTONE_FIELD_STRING = "is_delete";

    /**
     * 是否启用
     */
    @Override
    public boolean validate(List<String> list) {
        return true;
    }

    /**
     * 生成实体类控制函数
     *
     * @apiNote 添加头部注释和注解
     */
    @Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {

        // 添加实体类的 import
        topLevelClass.addImportedType("lombok.Data");
        topLevelClass.addImportedType("lombok.NoArgsConstructor");
        topLevelClass.addImportedType("lombok.AllArgsConstructor");
        topLevelClass.addJavaDocLine("/**");
        topLevelClass.addJavaDocLine(" * " + introspectedTable.getRemarks());
        topLevelClass.addJavaDocLine(" *");
        topLevelClass.addJavaDocLine(" * @author " + AUTHOR);
        topLevelClass.addJavaDocLine(" * @since " + LocalDate.now().format(DATE_STANDARD_FORMAT));
        topLevelClass.addJavaDocLine(" */");
        // 添加实体类的 lombok 注解
        topLevelClass.addAnnotation("@Data");
        topLevelClass.addAnnotation("@NoArgsConstructor");
        topLevelClass.addAnnotation("@AllArgsConstructor");

        return true;
    }

    /**
     * 生成实体成员变量控制函数
     *
     * @apiNote 添加实体成员变量的注释、将boolean还原为byte、区分datetime/date/time/timestamp转的Date
     */
    @Override
    public boolean modelFieldGenerated(Field field,
                                       TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn,
                                       IntrospectedTable introspectedTable,
                                       Plugin.ModelClassType modelClassType) {
        //将boolean还原为byte
        if (!TINYINT_CONVERT_BOOLEAN && field.getType().equals(new FullyQualifiedJavaType("java.lang.Boolean"))) {
            field.setType(new FullyQualifiedJavaType("java.lang.Byte"));
        } else if (field.getType().equals(new FullyQualifiedJavaType("java.util.Date"))) {
            //区分datetime、date、time、timestamp转的Date
            switch (introspectedColumn.getActualTypeName()) {
                case "DATETIME":
                case "TIMESTAMP":
                    field.setType(new FullyQualifiedJavaType("java.time.LocalDateTime"));
                    break;
                case "TIME":
                    field.setType(new FullyQualifiedJavaType("java.time.LocalTime"));
                    break;
                case "DATE":
                    field.setType(new FullyQualifiedJavaType("java.time.LocalDate"));
                    break;
                default:
                    break;
            }
        }
        //生成注释
        field.addJavaDocLine("/**");
        field.addJavaDocLine(" * " + introspectedColumn.getRemarks());
        field.addJavaDocLine(" */");
        return true;
    }

    /**
     * 实体类setter生成控制函数
     */
    @Override
    public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
        // 不生成 setter
        return false;
    }

    /**
     * 实体类getter生成控制函数
     */
    @Override
    public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
        // 不生成 getter
        return false;
    }

    /**
     * xml中的deleteByPrimaryKey控制函数
     *
     * @apiNote 增加逻辑删除功能
     */
    @Override
    public boolean sqlMapDeleteByPrimaryKeyElementGenerated(XmlElement element,
                                                            IntrospectedTable introspectedTable) {
        if (TOMBSTONE) {
            element.setName("update");
            List<VisitableElement> elements = element.getElements();
            //清空XmlElement的节点数据
            elements.clear();
            //增加update from #{table}行
            StringBuilder sb = new StringBuilder();
            sb.append("update from ");
            sb.append(introspectedTable.getFullyQualifiedTableNameAtRuntime());
            element.addElement(new TextElement(sb.toString()));
            //增加set行
            sb = new StringBuilder();
            sb.append("set ");
            sb.append(TOMBSTONE_FIELD_STRING);
            sb.append(" = 1");
            element.addElement(new TextElement(sb.toString()));
            //增加where行
            sb = new StringBuilder();
            sb.append("where ");
            List<IntrospectedColumn> primaryKeyColumns = introspectedTable.getPrimaryKeyColumns();
            for (IntrospectedColumn primaryKeyColumn : primaryKeyColumns) {
                sb.append(primaryKeyColumn.getActualColumnName());
                sb.append(" = ");
                sb.append(MyBatis3FormattingUtilities
                        .getParameterClause(primaryKeyColumn));
                sb.append(" and ");
            }
            //去除末尾的and
            sb.delete(sb.length() - 5, sb.length());
            element.addElement(new TextElement(sb.toString()));
        }
        //如果为false,则不生成deleteByPrimaryKey
        return true;
    }

    /**
     * mapper中deleteByPrimaryKey方法控制函数
     *
     * @apiNote 增加方法注释
     */
    @Override
    public boolean clientDeleteByPrimaryKeyMethodGenerated(Method method,
                                                           Interface interfaze, IntrospectedTable introspectedTable) {
        method.addJavaDocLine("/**");
        method.addJavaDocLine(" * 根据主键删除数据");
        addJavaDoc4PrimaryKeyMethod(method, introspectedTable);
        method.addJavaDocLine(" * @return 是否删除成功");
        method.addJavaDocLine(" * @author " + AUTHOR);
        method.addJavaDocLine(" * @since " + LocalDate.now().format(DATE_STANDARD_FORMAT));
        method.addJavaDocLine(" */");
        return true;
    }

    /**
     * xml中的SelectByPrimaryKey控制函数
     *
     * @apiNote 增加逻辑删除功能
     */
    @Override
    public boolean sqlMapSelectByPrimaryKeyElementGenerated(XmlElement element,
                                                            IntrospectedTable introspectedTable) {
        if (TOMBSTONE) {
            element.addElement(new TextElement(String.format(" and %s = 0", TOMBSTONE_FIELD_STRING)));
        }
        return true;
    }

    /**
     * mapper中selectByPrimaryKey方法控制函数
     *
     * @apiNote 增加方法注释
     */
    @Override
    public boolean clientSelectByPrimaryKeyMethodGenerated(Method method,
                                                           Interface interfaze, IntrospectedTable introspectedTable) {
        method.addJavaDocLine("/**");
        method.addJavaDocLine(" * 根据主键查找数据");
        addJavaDoc4PrimaryKeyMethod(method, introspectedTable);
        method.addJavaDocLine(" * @return 实体结果");
        method.addJavaDocLine(" * @author " + AUTHOR);
        method.addJavaDocLine(" * @since " + LocalDate.now().format(DATE_STANDARD_FORMAT));
        method.addJavaDocLine(" */");
        return true;
    }

    /**
     * 给相关PrimaryKeyMethod增加javadoc
     */
    private void addJavaDoc4PrimaryKeyMethod(Method method, IntrospectedTable introspectedTable) {
        method.addJavaDocLine(" *");
        for (int i = 0; i < method.getParameters().size(); i++) {
            Parameter parameter = method.getParameters().get(i);
            IntrospectedColumn column = introspectedTable.getPrimaryKeyColumns().get(i);
            method.addJavaDocLine(" * @param " + parameter.getName() + " " + column.getRemarks());
        }
    }


    /**
     * mapper中insert方法控制函数
     *
     * @apiNote 增加方法注释
     */
    @Override
    public boolean clientInsertMethodGenerated(Method method, Interface interfaze,
                                               IntrospectedTable introspectedTable) {
        method.addJavaDocLine("/**");
        method.addJavaDocLine(" * 向数据库中插入数据");
        addJavaDoc4DaoParamMethod(method, introspectedTable);
        method.addJavaDocLine(" */");
        return true;
    }

    /**
     * 给入参为Dao的相关方法增加javadoc,如insert、update等
     */
    private void addJavaDoc4DaoParamMethod(Method method, IntrospectedTable introspectedTable) {
        method.addJavaDocLine(" *");
        Parameter parameter = method.getParameters().get(0);
        method.addJavaDocLine(" * @param " + parameter.getName() + " " + introspectedTable.getRemarks() + "实体");
        method.addJavaDocLine(" * @author " + AUTHOR);
        method.addJavaDocLine(" * @since " + LocalDate.now().format(DATE_STANDARD_FORMAT));
    }

    /**
     * mapper中insertSelective方法控制函数
     *
     * @apiNote 增加方法注释
     */
    @Override
    public boolean clientInsertSelectiveMethodGenerated(Method method, Interface interfaze,
                                                        IntrospectedTable introspectedTable) {
        method.addJavaDocLine("/**");
        method.addJavaDocLine(" * 可选择地设置实体字段属性,插入到数据库中");
        addJavaDoc4DaoParamMethod(method, introspectedTable);
        method.addJavaDocLine(" */");
        return true;
    }

    /**
     * mapper中updateByPrimaryKeySelective方法控制函数
     *
     * @apiNote 增加方法注释
     */
    @Override
    public boolean clientUpdateByPrimaryKeySelectiveMethodGenerated(Method method,
                                                                    Interface interfaze, IntrospectedTable introspectedTable) {
        method.addJavaDocLine("/**");
        method.addJavaDocLine(" * 根据主键可选择地更新数据库中的相应字段");
        addJavaDoc4DaoParamMethod(method, introspectedTable);
        method.addJavaDocLine(" */");
        return true;
    }

    /**
     * mapper中updateByPrimaryKey方法控制函数
     *
     * @apiNote 增加方法注释
     */
    @Override
    public boolean clientUpdateByPrimaryKeyWithoutBLOBsMethodGenerated(Method method, Interface interfaze,
                                                                       IntrospectedTable introspectedTable) {
        method.addJavaDocLine("/**");
        method.addJavaDocLine(" * 根据主键更新数据库中的相应行");
        addJavaDoc4DaoParamMethod(method, introspectedTable);
        method.addJavaDocLine(" */");
        return true;
    }

    /**
     * mapper控制函数
     *
     * @apiNote 增加头部注释
     */
    @Override
    public boolean clientGenerated(Interface interfaze,
                                   IntrospectedTable introspectedTable) {
        interfaze.addJavaDocLine("/**");
        interfaze.addJavaDocLine(" * " + introspectedTable.getRemarks() + "映射接口");
        interfaze.addJavaDocLine(" *");
        interfaze.addJavaDocLine(" * @author " + AUTHOR);
        interfaze.addJavaDocLine(" * @since " + LocalDate.now().format(DATE_STANDARD_FORMAT));
        interfaze.addJavaDocLine("*/");
        return true;
    }

    /**
     * xml中Base_Column_List控制函数
     *
     * @apiNote 增加查询时根据RESULT_MAP_IGNORED忽略相应的列
     */
    @Override
    public boolean sqlMapBaseColumnListElementGenerated(XmlElement element,
                                                        IntrospectedTable introspectedTable) {

        List<VisitableElement> elements = element.getElements();
        List<VisitableElement> newElements = Lists.newArrayList();
        for (VisitableElement e : elements) {
            String content = ((TextElement) e).getContent();
            List<String> list = Splitter.on(',')
                    .trimResults()
                    .omitEmptyStrings()
                    .splitToList(content)
                    .stream()
                    .filter(a -> !RESULT_MAP_IGNORED.contains(a))
                    .collect(Collectors.toList());
            newElements.add(new TextElement(Joiner.on(", ").join(list)));
        }
        elements.clear();
        elements.addAll(newElements);
        return true;
    }

    /**
     * 是否覆盖原有xml
     */
    @Override
    public boolean sqlMapGenerated(GeneratedXmlFile sqlMap,
                                   IntrospectedTable introspectedTable) {
        sqlMap.setMergeable(false);
        return true;
    }
}

配置mybatis generator的配置文件generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>

    <context id="MyBatisGenerator" targetRuntime="MyBatis3">

        <!-- 整合 Mybatis 插件 -->
        <plugin type="com.xxxxxxx.common.MybatisPlugin" />

        <!-- 表名前后加上''的分隔符,部分数据库可能需要使用 -->
<!--        <property name="beginningDelimiter" value="`" />-->
<!--        <property name="endingDelimiter" value="`" />-->

        <commentGenerator>
            <!--不要注释 -->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>

        <!--这里是配置数据库链接 -->
        <jdbcConnection driverClass="你的数据库驱动"
                        connectionURL="你的jdbcURL"
                        userId="数据库账号"
                        password="数据库密码">
        </jdbcConnection>

        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>

        <!--这里是配置po -->
        <javaModelGenerator targetPackage="com.xxxxxx.po" targetProject="D:\Java\xxxxxxx\src\main\java">
            <property name="enableSubPackages" value="true"/>
            <property name="trimStrings" value="true"/>
            <!-- 这个是生成构造函数的,false没有构造函数但有setter和getter -->
            <!-- 用lombok后就不需要了 -->
<!--            <property name="constructorBased" value="true"/>-->
            <!-- 这个是生成构造函数的,true则只有构造函数没有setter和getter -->
<!--            <property name="immutable" value="true"/>-->
        </javaModelGenerator>

        <!--这里是配置mapper.xml -->
        <sqlMapGenerator targetPackage="mybatis.mapper" targetProject="D:\Java\xxxxxx\src\main\resources">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>

        <!--这里是配置mapper -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.xxxxxxx.mapper.base"
                             targetProject="D:\Java\xxxxxx\src\main\java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>

        <!--这里是数据库中的表,domainObjectName是要生成的类名,mapperName是要生成的Mapper以及Mapper.xml的名字,Example全设为false -->
        <table tableName="T_USER" domainObjectName="UserPO" mapperName="UserBaseMapper"
               enableCountByExample="false"
               enableUpdateByExample="false"
               enableDeleteByExample="false"
               enableSelectByExample="false"
               selectByExampleQueryId="false">
        </table>

    </context>

</generatorConfiguration>

运行generator

public class MybatisGenerator {
    public static void main(String[] args) throws Exception {
        List<String> warnings = new ArrayList<>();
        boolean overwrite = true;
        File file = new ClassPathResource("generatorConfig.xml").getFile();
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(file);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
    }
}

运行效果(展示图仅为样板,图片是旧的,具体见自己生成的代码),建议将生成的mapper放到mapper.base文件夹下,在mapper文件夹下新建子类Mapper并继承相应的父类BaseMapper,需要添加的接口放在子类Mapper中。子类的接口映射到的xml应为新建的Mapper.xml文件。调用时,使用子类Mapper,这样父类的方法也可以正常调用。
image.png
image.png
image.png

Mybatis分页插件-PageHelper

PageHelper是通过interceptor对mybatis查询进行分页的插件。

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>6.1.0</version>
</dependency>
@Configuration
public class PageHelperConfig {

    @Bean
    public Interceptor[] plugins() {
        return new Interceptor[]{new PageInterceptor()};
    }

}

分页使用

int currentPage = 1;
int pageSize = 3;
Page<EmployeeDao> page = new Page<>();
page.setCurrentPage(currentPage);
page.setPageSize(pageSize);
//分页查找员工信息
PageHelper.startPage(currentPage, pageSize);
List<EmployeeDao> list = employeeMapper.selectAllSelective(new EmployeeDao());
page.setTotalSize((int) ((com.github.pagehelper.Page<?>) list).getTotal());

查询结果
image.png

Mybatis-plus Code Generator

这是mybatis-plus mapper、repository、po、*mapper.xml的自动生成工具

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-generator</artifactId>
  <version>3.4.1</version>
</dependency>
public class MybatisPlusCodeGenerator {
    private final static String PARENT_PACKAGE_NAME = "com.你的项目包路径.你的项目包路径";
    private final static String OUT_DIR = "/src/main";

    public static final String DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";
    private static final String URL = "jdbc:mysql://localhost:3306/你的数据库?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai";
    private static final String USERNAME = "你的数据库用户名";
    public static final String PASSWORD = "你的数据库密码";

    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in, StandardCharsets.UTF_8.name());
        System.out.println("请输入" + tip + ":");
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "!");
    }

    public static void main(String[] args) {
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + OUT_DIR + "/java");
        gc.setAuthor("mybatisplus generator");
        gc.setOpen(false);
        //实体属性 Swagger2 注解
        //        gc.setSwagger2(true);
        gc.setFileOverride(true);
        gc.setEntityName("%sPO");
        gc.setServiceName("%sRepository");
        gc.setServiceImplName("%sRepositoryImpl");
        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(URL);
        dsc.setDriverName(DRIVER_CLASS_NAME);
        dsc.setUsername(USERNAME);
        dsc.setPassword(PASSWORD);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                String name = projectPath + OUT_DIR + "/resources/mybatis/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
                return name.replace("POMapper", "Mapper");
            }
        });
        cfg.setFileOutConfigList(focList);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setXml(null);
        templateConfig.setController(null);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig()
        .setEntityColumnConstant(true)
        .setEntityLombokModel(true)
        .setRestControllerStyle(false)
        //不生成id字段
        //                .setSuperEntityColumns("id")
        .setInclude(scanner("表名,多个英文逗号分割").split(","))
                .setControllerMappingHyphenStyle(false)
//                .setEntitySerialVersionUID(false)
                .setEntityBooleanColumnRemoveIsPrefix(true)
                .setEntityTableFieldAnnotationEnable(true)
                //表名下划线对应驼峰
                .setNaming(NamingStrategy.underline_to_camel)
                //设定表前缀,加上该配置后,会在表上自动生成@TableName注解
                .setTablePrefix("t_")
                .setColumnNaming(NamingStrategy.underline_to_camel);

        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent(PARENT_PACKAGE_NAME);
        packageConfig.setEntity("po");
        packageConfig.setMapper("mapper");
        packageConfig.setService("repository");
        packageConfig.setServiceImpl("repository.impl");
        new AutoGenerator().setGlobalConfig(gc)
                .setDataSource(dsc)
                .setCfg(cfg)
                .setStrategy(strategy)
                .setTemplate(templateConfig)
                .setTemplateEngine(new VelocityTemplateEngine())
                .setPackageInfo(packageConfig)
                .execute();
    }
}

一般table命名请使用 t 表 名 格式,启动代码后,在控制台中输入 {t_表名}格式,启动代码后,在控制台中输入 t格式,启动代码后,在控制台中输入{t_表名}(只是举例,于下面生成的文件不一致,无碍)
image.png
代码将会自动解析并生成相应的文件。
image.pngimage.png
image.pngimage.png

mapstruct

MapStruct 简单来说就是一个属性映射工具,主要用于解决数据模型之间不通用的情况。

<dependency>
  <groupId>org.mapstruct</groupId>
  <artifactId>mapstruct</artifactId>
  <version>1.5.5.Final</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>org.mapstruct</groupId>
  <artifactId>mapstruct-processor</artifactId>
  <version>1.5.5.Final</version>
  <scope>provided</scope>
</dependency>

MapStruct在映射时,默认将会匹配两个类中相同字段名的属性,并在编译时写入target中,如同lombok,MapStruct也可以在pom里写为<scope>provided</scope>,即只在编译和测试阶段起作用。
注明接口时,只需要在接口类上注上@Mapper(componentModel = "spring")注解,标明此类里的所有接口都需要MapStruct生成且需要spring统一管理,然后将需要转化的接口写好即可。
image.png
使用时如所有接口类,可使用@Autowired注解调用。
image.png

全局异常捕捉

全局异常捕捉主要为了防止运行异常没有try{……}catch(){……}导致整个APP崩溃、@Valid校验捕捉等。

@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理参数异常
     *
     * @param ex 参数异常
     * @return 格式化请求结果
     * @author xxxxxxx
     * @since 2024/7/23
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {

        BindingResult exceptions = ex.getBindingResult();
        // 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息
        if (exceptions.hasErrors()) {
            List<ObjectError> errors = exceptions.getAllErrors();
            if (!errors.isEmpty()) {
                for (ObjectError error : errors) {
                    log.warn("参数请求异常:{}", error.getDefaultMessage());
                }
                FieldError fieldError = (FieldError) errors.get(0);
                return Result.error(fieldError.getDefaultMessage());
            }
        }
        log.error("运行出错", ex);
        return Result.error("运行出错,请联系管理员");
    }

    /**
     * 处理其他异常
     *
     * @param e 异常
     * @return 格式化请求结果
     * @author xxxxxxx
     * @since 2024/7/23
     */
    @ExceptionHandler(Exception.class)
    public Result<String> handleException(Exception e) {
        log.error("运行出错", e);
        return Result.error("运行出错,请联系管理员");
    }
}
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值