1. package com.insigma.dict.plugin;
    2. import com.insigma.common.core.annotation.*;
    3. import com.insigma.common.core.utils.StringUtils;
    4. import com.insigma.sysdict.dto.input.SysDictInDTO;
    5. import com.insigma.sysdict.dto.output.SysDictOutDTO;
    6. import com.insigma.sysdict.feign.FeignServiceSysDict;
    7. import lombok.extern.slf4j.Slf4j;
    8. import org.apache.commons.collections4.CollectionUtils;
    9. import org.apache.ibatis.executor.resultset.ResultSetHandler;
    10. import org.apache.ibatis.plugin.*;
    11. import org.springframework.stereotype.Component;
    12. import javax.annotation.Resource;
    13. import java.lang.annotation.Annotation;
    14. import java.lang.reflect.Field;
    15. import java.sql.Statement;
    16. import java.util.*;
    17. // TODO 插入数据时 使用雪花算法生成分布式主键ID
    18. /** 1.查询结果处理数据字典 2.插入数据,使用雪花算法生成分布式主键ID */
    19. @Intercepts(
    20. @Signature(
    21. type = ResultSetHandler.class,
    22. method = "handleResultSets",
    23. args = {Statement.class}))
    24. @Slf4j
    25. @Component
    26. public class MybatisDictPlugin implements Interceptor {
    27. @Resource
    28. private FeignServiceSysDict feignServiceSysDict;
    29. @Override
    30. public Object intercept(Invocation invocation) throws Throwable {
    31. long startTime = System.currentTimeMillis();
    32. Object proceed = invocation.proceed();
    33. if (proceed instanceof List){
    34. List data = (List) proceed;
    35. if (StringUtils.isEmpty(data)) {
    36. return proceed;
    37. } else if (data.get(0) == null) {
    38. return Collections.emptyList();
    39. }
    40. // 遍历所有数据
    41. for (Object object : data) {
    42. if (object == null){
    43. continue;
    44. }
    45. Field[] declaredFields = object.getClass().getDeclaredFields();
    46. // 为了减少远程调用次数,将一个对象中所有需要字典翻译的字段放入map中,一次性请求,提高查询效率
    47. Map<Field, SysDictInDTO> map = new HashMap<>();
    48. for (Field field : declaredFields) {
    49. // 如果字段有dict注解
    50. if (field.isAnnotationPresent(Dict.class)){
    51. Annotation[] annotations = field.getAnnotations();
    52. for (Annotation annotation : annotations) {
    53. if (annotation.annotationType().equals(Dict.class)){
    54. Dict dict = (Dict) annotation;
    55. String dicCode = dict.dicCode();
    56. // 设置字段可访问, 否则无法访问private修饰的变量值
    57. field.setAccessible(true);
    58. Object value = field.get(object);
    59. if (value != null){
    60. // 根据dictCode和value查询中文解释
    61. SysDictInDTO sysDictInDTO = new SysDictInDTO();
    62. sysDictInDTO.setDictCode(dicCode);
    63. sysDictInDTO.setDictValue(value.toString());
    64. map.put(field, sysDictInDTO);
    65. }
    66. }
    67. }
    68. }
    69. }
    70. if (map.size() > 0){
    71. // 查询字典服务
    72. ArrayList<SysDictInDTO> sysDictInDTOS = new ArrayList<>(map.values());
    73. List<SysDictOutDTO> sysDictOutDTOList = feignServiceSysDict.queryDictListByCodeAndValue(sysDictInDTOS);
    74. if (CollectionUtils.isNotEmpty(sysDictOutDTOList)){
    75. for (Field field : map.keySet()) {
    76. for (SysDictOutDTO sysDictOutDTO : sysDictOutDTOList) {
    77. SysDictInDTO sysDictInDTO = map.get(field);
    78. if (Objects.equals(sysDictInDTO.getDictCode(), sysDictOutDTO.getDictCode())){
    79. field.set(object, sysDictOutDTO.getItemText());
    80. }
    81. }
    82. }
    83. }
    84. }
    85. }
    86. }
    87. log.info("MybatisDictPlugin.intercept cost:{} ms", System.currentTimeMillis()-startTime);
    88. return proceed;
    89. }
    90. @Override
    91. public Object plugin(Object target) {
    92. return Plugin.wrap(target, this);
    93. }
    94. @Override
    95. public void setProperties(Properties properties) {}
    96. }
    package com.insigma.sysdict.feign;
    
    import com.insigma.sysdict.hystrix.HystrixServiceSysDict;
    import com.insigma.sysdict.service.api.SysDictService;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.stereotype.Repository;
    
    @FeignClient(name = "app-dpes-sysdict",fallbackFactory = HystrixServiceSysDict.class)
    @Repository
    public interface FeignServiceSysDict extends SysDictService {
    
    }
    
    package com.insigma.sysdict.dto.input;
    
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    import javax.validation.Valid;
    import javax.validation.constraints.NotNull;
    import java.io.Serializable;
    
    @Data
    @Valid
    @ApiModel(value = "数据字典接收参数")
    public class SysDictInDTO implements Serializable {
    
        @NotNull(message = "字典编码不能为空!")
        @ApiModelProperty(value = "字典编码")
        private String dictCode;
        private String dictText;
        private String dictType;
        private String dictValue;
    }
    
    package com.insigma.common.core.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @author Jiangchao
     * @description: TODO
     * @date 2022/3/9 14:10
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Dict {
        /**
         * 方法描述:  数据code
         * 作    者: dangzhenghui
         * 日    期: 2019年03月17日-下午9:37:16
         *
         * @return 返回类型: String
         */
        String dicCode();
    
        /**
         * 方法描述:  数据Text
         * 作    者: dangzhenghui
         * 日    期: 2019年03月17日-下午9:37:16
         *
         * @return 返回类型: String
         */
        String dicText() default "";
    
        /**
         * 方法描述: 数据字典表
         * 作    者: dangzhenghui
         * 日    期: 2019年03月17日-下午9:37:16
         *
         * @return 返回类型: String
         */
        String dictTable() default "";
    }
    
    package com.insigma.sysdict.dto.output;
    
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    
    import java.io.Serializable;
    import java.util.List;
    
    @Data
    @ApiModel(value = "数据字典返回参数")
    public class SysDictOutDTO implements Serializable {
        @ApiModelProperty(value = "ID")
        private String id;
        @ApiModelProperty(value = "字典名称")
        private String itemText;
        @ApiModelProperty(value = "字典值")
        private String itemValue;
        @ApiModelProperty(value = "父级ID")
        private String superId;
        @ApiModelProperty(value = "字典编码")
        private String dictCode;
    
        private List<SysDictOutDTO> dictOutDTOS;
    
    }
    
    package com.insigma.sysdict.service.api;
    
    import com.alibaba.fastjson.JSONObject;
    import com.insigma.common.core.constants.DictConstant;
    import com.insigma.common.core.domain.BaseResponse;
    import com.insigma.sysdict.dto.input.SysDictInDTO;
    import com.insigma.sysdict.dto.output.DictOutDTO;
    import com.insigma.sysdict.dto.output.SysDictOutDTO;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiImplicitParam;
    import io.swagger.annotations.ApiImplicitParams;
    import io.swagger.annotations.ApiOperation;
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    import java.util.Map;
    
    @Api(tags = "数据字典服务接口")
    @RequestMapping("app-dpes-sysdict")
    public interface SysDictService {
    
        //@ApiOperation(value = "根据代码获取数据字典")
        //@PostMapping("/getDict")
        //@CrossOrigin
        //BaseResponse<JSONObject> getDictCode(@ModelAttribute("sysDictInDTO") @Validated SysDictInDTO sysDictInDTO);
    
        @PostMapping("/parseDictText")
        @CrossOrigin
        String parseDictText(@RequestParam("listClassName") String listClassName, @RequestParam("type") String type, @RequestBody BaseResponse baseResponse);
    
        @GetMapping("/queryDictByDiCode")
        @ApiOperation(value = "根据父代码,类别查列表")
        @CrossOrigin
        BaseResponse<List<DictOutDTO>> queryDictByDiCode(@RequestParam("itemValue") String itemValue, @RequestParam("code") String code);
    
    
        @GetMapping("/queryDictTextByDiCode")
        @ApiOperation(value = "各种下拉框")
        @CrossOrigin
        BaseResponse<List<Map<String, String>>> queryDictTextByDiCode(@RequestParam("code") String code);
    
        @GetMapping("/queryDictValueByDiCode")
        @ApiOperation(value = "获取字典值,模糊搜索")
        @CrossOrigin
        String queryDictValueByDiCode(@RequestParam("dictCode") String dictCode, @RequestParam("dictText") String dictText);
    
        @GetMapping("/getCodeByCityName")
        @ApiOperation(value = "模糊获取cityId")
        @CrossOrigin
        BaseResponse getCodeByCityName(@RequestParam("city") String city);
        @GetMapping("/getThreeCityListByCityName")
        @ApiOperation(value = "根据城市名称获取区县列表")
        @CrossOrigin
        List<DictOutDTO> getThreeCityListByCityName(@RequestParam("city") String city);
    
        @GetMapping("/getJobClassThree")
        @ApiOperation(value = "职位类别三级联动")
        @CrossOrigin
        BaseResponse<List<DictOutDTO>> getJobClassThree();
    
        @GetMapping("/getHyTwoList")
        @ApiOperation(value = "职位行业三级联动")
        @CrossOrigin
        BaseResponse<List<DictOutDTO>> getHyTwoList();
    
        @GetMapping("/getThreeCityList")
        @ApiOperation(value = "职位行业三级联动")
        @CrossOrigin
        List<DictOutDTO> getThreeCityList();
    
        @PostMapping("/queryDictByCodeAndValue")
        @ApiOperation(value = "查询字典信息")
        @CrossOrigin
        SysDictOutDTO queryDictByCodeAndValue(@RequestBody SysDictInDTO sysDictInDTO);
    
        @PostMapping("/queryDictListByCodeAndValue")
        @ApiOperation(value = "批量查询字典信息")
        @CrossOrigin
        List<SysDictOutDTO> queryDictListByCodeAndValue(@RequestBody List<SysDictInDTO> sysDictInDTOList);
    
        @GetMapping("/queryDictById")
        @ApiOperation(value = "查询字典信息")
        @CrossOrigin
        SysDictOutDTO queryDictById(String id);
    
        @GetMapping("/seachJobClassBythree")
        @ApiOperation(value = "搜索第三极,逆推第二级")
        @CrossOrigin
        BaseResponse<List<DictOutDTO>> seachJobClassBythree(@RequestParam("search") String search);
    
        //@GetMapping("/getCityParams/{type}")
        //BaseResponse getCityParams(@PathVariable(name = "type", required = false) String type);
    
        @ApiOperation(value = "根据dictType获取数据字典信息")
        @GetMapping("/getDict/{dictType}")
        @Cacheable(cacheNames = "DictLevel", key = "#dictType", unless = "#result==null")
        BaseResponse getDictLevel(@PathVariable(name = "dictType") String dictType);
    
        @ApiOperation(value = "根据codeType获取数据CodeValue字典信息")
        @GetMapping("/getCodeValue")
        @Cacheable(value = "CodeValue", key = "T(String).valueOf(#dictType).concat('-').concat(#dictLevel)", unless = "#result==null")
        BaseResponse getCodeValue(@RequestParam(name = "dictType") String dictType,
                                         @RequestParam(name = "dictLevel", required = false, defaultValue = "1") String dictLevel);
    
    
        //最终数据字典服务接口,1级,2级,3级
        @ApiOperation(value = "根据codeType获取数据CodeValue字典信息")
        @ApiImplicitParams({
                @ApiImplicitParam(name = "maxLevel", value = "最多的层级,-1代表最大可能", defaultValue = "-1"),
                @ApiImplicitParam(name = "dictValue", value = "父级代码值"),
                @ApiImplicitParam(name = "dictCode", value = "商品分类:product_fir"),
                @ApiImplicitParam(name = "dictCode", value = "到岗时间:arrival_time"),
                @ApiImplicitParam(name = "dictCode", value = "发布时间:publish_date"),
                @ApiImplicitParam(name = "dictCode", value = "地区:provinceid"),
                @ApiImplicitParam(name = "dictCode", value = "残疾类别:disabled_type"),
                @ApiImplicitParam(name = "dictCode", value = "职位类型:job1"),
                @ApiImplicitParam(name = "dictCode", value = "行业:hy1"),
                @ApiImplicitParam(name = "dictCode", value = "职位薪资:user_salary"),
                @ApiImplicitParam(name = "dictCode", value = "工作经验:user_word"),
                @ApiImplicitParam(name = "dictCode", value = "学历:user_edu"),
                @ApiImplicitParam(name = "dictCode", value = "性别:user_sex"),
                @ApiImplicitParam(name = "dictCode", value = "职位特色:job_tese"),
                @ApiImplicitParam(name = "dictCode", value = "公司性质,企业类型:pr"),
                @ApiImplicitParam(name = "dictCode", value = "职位类型:job_type"),
                @ApiImplicitParam(name = "dictCode", value = "职位人数:job_number"),
                @ApiImplicitParam(name = "dictCode", value = "专栏分类:clum_class"),
        })
        @GetMapping("/commonDictValue")
        public BaseResponse commonDictValue(@RequestParam(name = "dictCode") String dictType,
                                            @RequestParam(name = "dictValue", required = false, defaultValue = "-1") String dictValue,
                                            @RequestParam(name = "maxLevel", required = false, defaultValue = "-1") String dictLevel);
    
        @ApiOperation(value = "根据市区代码获取省代码")
        @PostMapping("/getProvinceByCityId")
        BaseResponse getProvinceByCityId(@RequestParam(name = "city") String city);
    
        @ApiOperation(value = "根据市区代码获取省代码")
        @GetMapping("/根据汉字获取代码")
        String selectCodeByCha(@RequestParam(name = "codeName") String codeName);
    }