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; } }