huangzhen
2023-09-07 2dfc2dfa627d413dfbfe0276d51332680afa5eff
增加全局异常;区划缓存
已修改2个文件
已添加9个文件
524 ■■■■■ 文件已修改
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDistrictController.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/ResultConstants.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/BusinessException.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/ExceptionInfo.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDistrict.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/resp/DistrictTreeRespDTO.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDistrictMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/SysDistrictService.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDistrictServiceImpl.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDistrictController.java
对比新文件
@@ -0,0 +1,48 @@
package com.ruoyi.web.controller.system;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.domain.SysDistrict;
import com.ruoyi.system.domain.resp.DistrictTreeRespDTO;
import com.ruoyi.system.service.SysDistrictService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;
import static com.ruoyi.common.core.domain.AjaxResult.success;
/**
 * @author hz
 * @since 2023-09-07 13:13:47
 */
@RestController
@RequestMapping("/system/sysDistrict/")
public class SysDistrictController {
    /**
     * 获取所有
     */
    @Resource
    private SysDistrictService sysDistrictService;
    @GetMapping("/list")
    public AjaxResult selectAll() {
        List<SysDistrict> sysDistricts = sysDistrictService.selectAll();
        return AjaxResult.success(sysDistricts);
    }
    /**
     * 树状返回
     *
     */
    @GetMapping("/tree")
    public AjaxResult selectAllByTree() {
        List<DistrictTreeRespDTO> sysDistricts = sysDistrictService.selectAllByTree();
        return AjaxResult.success(sysDistricts);
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java
@@ -27,6 +27,11 @@
     */
    public static final String SYS_DICT_KEY = "sys_dict:";
    public static final String SYS_DISTRICT_LIST_KEY = "sys_district_list";
    public static final String SYS_DISTRICT_TREE_KEY = "sys_district_tree";
    /**
     * 防重提交 redis key
     */
ruoyi-common/src/main/java/com/ruoyi/common/constant/ResultConstants.java
对比新文件
@@ -0,0 +1,88 @@
package com.ruoyi.common.constant;
import java.util.HashMap;
import java.util.Map;
public enum ResultConstants {
    //正常
    OK(200,"成功"),
    NOT_OK(500,"错误"),
    //参数错误
    PARAM_ERROR(300,"参数错误"),
    PARAM_ERROR_NULL(301,"参数不能为空"),
    PARAM_ERROR_ILLEGAL(301,"参数格式错误"),
    PARAM_ERROR_OUT_OF_RANGE(302,"参数超出限制"),
    //业务错误
    BUSINESS_ERROR(400,"业务错误"),
    BUSINESS_ERROR_ACCOUNT_NOT_EXIST(401,"用户不存在"),
    BUSINESS_ERROR_ACCOUNT_STATU_ABNORMAL(402,"账号异常"),
    BUSINESS_ERROR_ACCOUNT_OFFLINE(403,"用户未登录"),
    BUSINESS_ERROR_PERMISSION_DENIALED(405,"操作未授权"),
    BUSINESS_ERROR_OUT_OF_TIME(406,"业务超时"),
    BUSINESS_ERROR_OBJECT_NOT_EXIST(407,"业务单元不存在"),
    BUSINESS_ERROR_NOT_ALLOWED(408,"业务不允许"),
    BUSINESS_ERROR_HTTP_METHOD_NOT_SUPPORT(409,"HTTP请求方法不支持"),
    BUSINESS_ERROR_DATA_NOT_EXISIST(410,"数据不存在"),
    //系统错误
    SYSTEM_ERROR(500,"系统出错"),
    SYSTEM_ERROR_API_FAIL(501,"接口错误"),
    SYSTEM_ERROR_API_OUT_OF_TIME(502,"接口超时"),
    SYSTEM_ERROR_DATABASE_FAIL(503,"数据库错误"),
    SYSTEM_ERROR_SERIALIZA_FAIL(504,"序列化错误"),
    //文件
    FILE_NOT_EXISIST(600,"文件不存在"),
    PATH_NOT_EXISIST(601,"文件路径不存在"),
    MODULE_NOT_EXISIST(602,"模块不存在"),
    FILE_UPLOAD_FAIL(603,"文件上传失败"),
    FILE_DOWNLOAD_FAIL(604,"文件下载失败"),
    FILE_DOWNLOAD_EXPERTION(605,"文件下载异常"),
    ;
    ResultConstants(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }
    private Integer code;
    private String desc;
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public String getDesc() {
        return desc;
    }
    public void setDesc(String desc) {
        this.desc = desc;
    }
    static Map<Integer,ResultConstants> map;
    static {
        map = new HashMap<>();
        for(ResultConstants rc : ResultConstants.values()){
            map.put(rc.getCode(),rc);
        }
    }
    public static ResultConstants prase(Integer code){
        return map.get(code);
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/BusinessException.java
对比新文件
@@ -0,0 +1,74 @@
package com.ruoyi.common.exception;
import com.ruoyi.common.constant.ResultConstants;
public class BusinessException extends RuntimeException {
    private Class causeClass;
    private Integer code;
    private String message;
//    public BusinessException(ResultCode error) {
//        super(error.getDesc());
//        this.code = error.getCode();
//        this.message = error.getDesc();
//    }
    public BusinessException(Class causeClass, ResultConstants error) {
        super(error.getDesc());
        this.causeClass = causeClass;
        this.code = error.getCode();
        this.message = error.getDesc();
    }
    public BusinessException(Class causeClass, ResultConstants error, String message) {
        super(error.getDesc());
        this.causeClass = causeClass;
        this.code = error.getCode();
        if(message != null && !message.isEmpty()){
            this.message = message;
        }else {
            this.message = error.getDesc();
        }
    }
//    public BusinessException(Integer code, String message) {
//        super(message);
//        this.code = code;
//        this.message = message;
//    }
    public BusinessException(Class causeClass, Integer code, String message) {
        super(message);
        this.causeClass = causeClass;
        this.code = code;
        this.message = message;
    }
    public Class getCauseClass() {
        return causeClass;
    }
    public void setCauseClass(Class causeClass) {
        this.causeClass = causeClass;
    }
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    @Override
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/ExceptionInfo.java
对比新文件
@@ -0,0 +1,46 @@
package com.ruoyi.common.exception;
import java.time.LocalDateTime;
public class ExceptionInfo {
    private Class causeClass;
    private LocalDateTime time;
    private Integer code;
    private String msg;
    public Class getCauseClass() {
        return causeClass;
    }
    public void setCauseClass(Class causeClass) {
        this.causeClass = causeClass;
    }
    public LocalDateTime getTime() {
        return time;
    }
    public void setTime(LocalDateTime time) {
        this.time = time;
    }
    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;
    }
}
ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
@@ -1,14 +1,22 @@
package com.ruoyi.framework.web.exception;
import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.constant.ResultConstants;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.exception.ExceptionInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import com.ruoyi.common.constant.HttpStatus;
@@ -16,6 +24,8 @@
import com.ruoyi.common.exception.DemoModeException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import java.time.LocalDateTime;
/**
 * 全局异常处理器
@@ -27,6 +37,31 @@
{
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    @Autowired
    private ObjectMapper objectMapper;
    /**
     * 通用异常
     */
    @ResponseBody
    @ExceptionHandler(value = BusinessException.class)
    public AjaxResult businessExceptionHandler(BusinessException e) throws JsonProcessingException {
        ExceptionInfo exceptionInfo = new ExceptionInfo();
        exceptionInfo.setTime(LocalDateTime.now());
        exceptionInfo.setCode(e.getCode());
        exceptionInfo.setMsg(e.getMessage());
        exceptionInfo.setCauseClass(e.getCauseClass());
        log.error(objectMapper.writeValueAsString(exceptionInfo));
        if(e.getMessage() == null || e.getMessage().isEmpty()){
            ResultConstants code = ResultConstants.prase(e.getCode());
            if(code != null)
                return AjaxResult.error(e.getCode(),code.getDesc());
        }else {
            return AjaxResult.error(e.getCode(),e.getMessage());
        }
        return AjaxResult.error();
    }
    /**
     * 权限校验异常
     */
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDistrict.java
对比新文件
@@ -0,0 +1,25 @@
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import java.io.Serializable;
/**
 * @author hz
 * @since 2023-09-07 13:13:57
 */
@Data
public class SysDistrict implements Serializable {
    private Long id;
    private String code;
    private String name;
    private String parentcode;
    private Byte type;
}
ruoyi-system/src/main/java/com/ruoyi/system/domain/resp/DistrictTreeRespDTO.java
对比新文件
@@ -0,0 +1,27 @@
package com.ruoyi.system.domain.resp;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
 * @author Mr.huang
 * @decription
 * @date 2023/9/7 15:22
 */
@Data
public class DistrictTreeRespDTO implements Serializable {
    private Long id;
    private String code;
    private String name;
    private String parentcode;
    private Byte type;
    private List<DistrictTreeRespDTO> children;
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDistrictMapper.java
对比新文件
@@ -0,0 +1,15 @@
package com.ruoyi.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.system.domain.SysDistrict;
import org.springframework.stereotype.Repository;
/**
 * @author hz
 * @since 2023-09-07 13:13:52
 */
@Repository
public interface SysDistrictMapper extends BaseMapper<SysDistrict> {
}
ruoyi-system/src/main/java/com/ruoyi/system/service/SysDistrictService.java
对比新文件
@@ -0,0 +1,35 @@
package com.ruoyi.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.domain.SysDistrict;
import com.ruoyi.system.domain.resp.DistrictTreeRespDTO;
import java.util.List;
/**
 * @author hz
 * @since 2023-09-07 13:13:57
 */
public interface SysDistrictService extends IService<SysDistrict> {
    List<SysDistrict> selectAll();
    /**
     * 加载字典缓存数据
     */
    public void loadingDistrictCache();
    /**
     * 清空字典缓存数据
     */
    public void clearDistrictCache();
    /**
     * 重置字典缓存数据
     */
    public void resetDistrictCache();
    List<DistrictTreeRespDTO> selectAllByTree();
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDistrictServiceImpl.java
对比新文件
@@ -0,0 +1,126 @@
package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.ResultConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.resp.DistrictTreeRespDTO;
import com.ruoyi.system.mapper.SysDistrictMapper;
import com.ruoyi.system.domain.SysDistrict;
import com.ruoyi.system.service.SysDistrictService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;
import static com.ruoyi.common.utils.DictUtils.clearDictCache;
/**
 * @author hz
 * @since 2023-09-07 13:13:58
 */
@Service("sysDistrictService")
public class SysDistrictServiceImpl extends ServiceImpl<SysDistrictMapper, SysDistrict> implements SysDistrictService {
    @PostConstruct
    public void init()
    {
        loadingDistrictCache();
    }
    @Override
    public List<SysDistrict> selectAll() {
        if (SpringUtils.getBean(RedisCache.class).hasKey(CacheConstants.SYS_DISTRICT_LIST_KEY)){
            List<SysDistrict> sysDistricts = SpringUtils.getBean(RedisCache.class).getCacheObject(CacheConstants.SYS_DISTRICT_LIST_KEY);
            return sysDistricts;
        }
        List<SysDistrict> list = this.list();
        SpringUtils.getBean(RedisCache.class).setCacheObject(CacheConstants.SYS_DISTRICT_LIST_KEY, list);
        return list;
    }
    @Override
    public void loadingDistrictCache()
    {
        List<SysDistrict> list = this.list();
        if (!CollectionUtils.isEmpty(list)) {
            SpringUtils.getBean(RedisCache.class).setCacheObject(CacheConstants.SYS_DISTRICT_LIST_KEY, list);
        }
        List<DistrictTreeRespDTO> treeRespDTOS = this.selectAllByTree();
        if (!CollectionUtils.isEmpty(treeRespDTOS)) {
            SpringUtils.getBean(RedisCache.class).setCacheObject(CacheConstants.SYS_DISTRICT_TREE_KEY, list);
        }
    }
    @Override
    public void clearDistrictCache()
    {
        if (SpringUtils.getBean(RedisCache.class).hasKey(CacheConstants.SYS_DISTRICT_LIST_KEY)){
            SpringUtils.getBean(RedisCache.class).deleteObject(CacheConstants.SYS_DISTRICT_LIST_KEY);
        }
        if (SpringUtils.getBean(RedisCache.class).hasKey(CacheConstants.SYS_DISTRICT_TREE_KEY)){
            SpringUtils.getBean(RedisCache.class).deleteObject(CacheConstants.SYS_DISTRICT_TREE_KEY);
        }
    }
    /**
     * 重置区划缓存数据
     */
    @Override
    public void resetDistrictCache()
    {
        clearDistrictCache();
        loadingDistrictCache();
    }
    @Override
    public List<DistrictTreeRespDTO> selectAllByTree() {
        if (SpringUtils.getBean(RedisCache.class).hasKey(CacheConstants.SYS_DISTRICT_TREE_KEY)){
            List<DistrictTreeRespDTO> sysDistrictTree = SpringUtils.getBean(RedisCache.class).getCacheObject(CacheConstants.SYS_DISTRICT_TREE_KEY);
            return sysDistrictTree;
        }
        List<SysDistrict> districts = this.selectAll();
        if (CollectionUtils.isEmpty(districts)){
            throw new BusinessException(this.getClass(), ResultConstants.SYSTEM_ERROR_DATABASE_FAIL,"区划信息获取失败");
        }
        //获取父节点,0表示父节点,让此次递归有个开头
        List<DistrictTreeRespDTO> collect = districts.stream()
                //父节点的id = 0,根据它开始进行实现。
                .filter(e -> e.getParentcode().equals("0"))
                .map(e ->{
                    DistrictTreeRespDTO dto = new DistrictTreeRespDTO();
                    BeanUtils.copyProperties(e,dto);
                    //将过滤之后的数据来进行方法调用,拿到他的所有的子节点信息并进行封装
                    dto.setChildren(getchildrens(dto, districts));
                    return dto;
                }).collect(Collectors.toList());
        SpringUtils.getBean(RedisCache.class).setCacheObject(CacheConstants.SYS_DISTRICT_TREE_KEY, collect);
        return collect;
    }
    private List<DistrictTreeRespDTO> getchildrens(DistrictTreeRespDTO root,List<SysDistrict> districts){
        //root为每次最新的传递过来的数据,也就是上面过滤之后的 e ;
        List<DistrictTreeRespDTO> collect = districts.stream()
                //根据传递过来的 e ,拿到他的id,来查询出他的子节点id 这里有个特点 e.id = 子节点的父节点id
                .filter(e -> Objects.equals(e.getParentcode(), root.getCode()))
                .map(e -> {
                    DistrictTreeRespDTO dto = new DistrictTreeRespDTO();
                    BeanUtils.copyProperties(e,dto);
                    dto.setChildren(getchildrens(dto, districts));
                    //递归找到他的子节点,直到找到最后一个子节点为止,饼进行封装。
                    return dto;
                }).collect(Collectors.toList());
        return collect;
    }
}