本篇博客主要聊聊自定义注解在项目中的应用,自定义注解用来做系统监控日志,这个用法已经烂大街了,无法让面试官眼前一亮的感觉。
项目开发中数据字典使用场景非常多,使用数据字典有一点非常的不方便,那就是数据库中存放的是数字,而实际页面上展示的却是汉字;那么这也就造成了,每次做页面展示的时候都需要给数字进行转义,将其转义成汉字内容展示到页面,而转换的过程过于繁琐;
咱们的自定义注解可以完美的解决这一问题;
浏览器输入:http://localhost:8080/student/listPager 测试
最后浏览器访问的效果图
当然,也可以不走默认规则,xxx就是在类属性上的自定义注解的属性值
相关的pom依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.4</version> </dependency>
逆向工程生成实体类、mapper.xml、mapper.java
实体类
package com.javaxl.model; public class DataDict { private Integer id; private String datasource; private String description; public DataDict(Integer id, String datasource, String description) { this.id = id; this.datasource = datasource; this.description = description; } public DataDict() { super(); } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getDatasource() { return datasource; } public void setDatasource(String datasource) { this.datasource = datasource; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
package com.javaxl.model; public class DataItem { private Integer id; private String datasource; private String code; private String val; public DataItem(Integer id, String datasource, String code, String val) { this.id = id; this.datasource = datasource; this.code = code; this.val = val; } public DataItem() { super(); } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getDatasource() { return datasource; } public void setDatasource(String datasource) { this.datasource = datasource; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getVal() { return val; } public void setVal(String val) { this.val = val; } }
package com.javaxl.model; import com.javaxl.annotation.Dict; public class Student { private Integer id; private String name; @Dict(dicDataSource = "stu_Level") private Integer stulevel; @Dict(dicDataSource = "stu_English",dicText = "xxx") private Integer englishlevel; @Dict(dicDataSource = "stu_hobby") private String stuhobby; public Student(Integer id, String name, Integer stulevel, Integer englishlevel, String stuhobby) { this.id = id; this.name = name; this.stulevel = stulevel; this.englishlevel = englishlevel; this.stuhobby = stuhobby; } public Student() { super(); } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getStulevel() { return stulevel; } public void setStulevel(Integer stulevel) { this.stulevel = stulevel; } public Integer getEnglishlevel() { return englishlevel; } public void setEnglishlevel(Integer englishlevel) { this.englishlevel = englishlevel; } public String getStuhobby() { return stuhobby; } public void setStuhobby(String stuhobby) { this.stuhobby = stuhobby; } }
Mapper.java
package com.javaxl.mapper; import com.javaxl.model.DataDict; public interface DataDictMapper { int deleteByPrimaryKey(Integer id); int insert(DataDict record); int insertSelective(DataDict record); DataDict selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(DataDict record); int updateByPrimaryKey(DataDict record); }
package com.javaxl.mapper; import com.javaxl.model.DataItem; import org.springframework.stereotype.Repository; import org.springframework.web.bind.annotation.ResponseBody; @Repository public interface DataItemMapper { int deleteByPrimaryKey(Integer id); int insert(DataItem record); int insertSelective(DataItem record); DataItem selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(DataItem record); int updateByPrimaryKey(DataItem record); DataItem selectByDatasourceCode(DataItem dataItem); }
package com.javaxl.mapper; import com.javaxl.model.Student; import org.springframework.stereotype.Repository; import java.util.List; @Repository public interface StudentMapper { int deleteByPrimaryKey(Integer id); int insert(Student record); int insertSelective(Student record); Student selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(Student record); int updateByPrimaryKey(Student record); List<Student> listPager(Student student); }
Service层
package com.javaxl.service; import com.javaxl.model.DataItem; /** * @author 小李飞刀 * @site www.javaxl.com * @company * @create 2019-11-24 20:56 */ public interface DataItemService { DataItem selectByDatasourceKey(DataItem dataItem); String selectByDatasourceKey(String dataSource, String key); }
package com.javaxl.service; import com.javaxl.model.Student; import com.javaxl.util.PageBean; import java.util.List; /** * @author 小李飞刀 * @site www.javaxl.com * @company * @create 2019-11-24 20:51 */ public interface StudentService { List<Student> listPager(Student student, PageBean pageBean); }
package com.javaxl.service.impl; import com.javaxl.mapper.DataItemMapper; import com.javaxl.model.DataItem; import com.javaxl.service.DataItemService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @author 小李飞刀 * @site www.javaxl.com * @company * @create 2019-11-24 21:01 */ @Service public class DataItemServiceImpl implements DataItemService { @Autowired private DataItemMapper dataItemMapper; @Override public DataItem selectByDatasourceKey(DataItem dataItem) { return dataItemMapper.selectByDatasourceCode(dataItem); } @Override public String selectByDatasourceKey(String dataSource, String key) { DataItem dataItem = new DataItem(); dataItem.setDatasource(dataSource); dataItem.setCode(key); return dataItemMapper.selectByDatasourceCode(dataItem).getVal(); } }
package com.javaxl.service.impl; import com.javaxl.mapper.StudentMapper; import com.javaxl.model.Student; import com.javaxl.service.StudentService; import com.javaxl.util.PageBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * @author 小李飞刀 * @site www.javaxl.com * @company * @create 2019-11-24 20:54 */ @Service public class StudentServiceImpl implements StudentService { @Autowired private StudentMapper studentMapper; @Override public List<Student> listPager(Student student, PageBean pageBean) { return studentMapper.listPager(student); } }
重点代码来了
package com.javaxl.controller; import com.javaxl.model.Student; import com.javaxl.service.StudentService; import com.javaxl.util.PageBean; import com.javaxl.util.PageUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import java.util.List; /** * @author 小李飞刀 * @site www.javaxl.com * @company * @create 2019-11-24 21:06 */ @Controller @RequestMapping("/student") public class StudentController { @Autowired private StudentService studentService; @ResponseBody @RequestMapping("/listPager") public PageUtils listPager(Student student, HttpServletRequest req){ PageBean pageBean = new PageBean(); pageBean.setRequest(req); List<Student> list = this.studentService.listPager(student,pageBean); PageUtils pageUtils = new PageUtils(list,pageBean.getTotal()); return pageUtils; } }
DictAspect.java
package com.javaxl.aspect; import com.alibaba.fastjson.JSONObject; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.javaxl.annotation.Dict; import com.javaxl.service.DataItemService; import com.javaxl.util.ObjConvertUtils; import com.javaxl.util.PageUtils; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import java.lang.reflect.Field; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * @author 小李飞刀 * @site www.javaxl.com * @company * @create 2019-11-24 20:39 */ @Aspect @Component @Slf4j public class DictAspect { private static String DICT_TEXT_SUFFIX = "_dictText"; @Autowired private DataItemService dataItemService; // 定义切点Pointcut 拦截所有对服务器的请求 @Pointcut("execution( * com.javaxl.controller.*.*(..))") public void excudeService() { } /** * 这是触发 excudeService 的时候会执行的,在环绕通知中目标对象方法被调用后的结果进行再处理 * * @param pjp * @return * @throws Throwable */ @Around("excudeService()") public Object doAround(ProceedingJoinPoint pjp) throws Throwable { //这是定义开始事件 long time1 = System.currentTimeMillis(); //这是方法并获取返回结果 Object result = pjp.proceed(); //这是获取到 结束时间 long time2 = System.currentTimeMillis(); log.debug("获取JSON数据 耗时:" + (time2 - time1) + "ms"); //解析开始时间 long start = System.currentTimeMillis(); //开始解析(翻译字段内部的值凡是打了 @Dict 这玩意的都会被翻译) this.parseDictText(result); //解析结束时间 long end = System.currentTimeMillis(); log.debug("解析注入JSON数据 耗时" + (end - start) + "ms"); return result; } /** * 本方法针对返回对象为Result 的PageUtils的分页列表数据进行动态字典注入 * 字典注入实现 通过对实体类添加注解@dict 来标识需要的字典内容,字典分为单字典dataSource即可 * 示例为Student * 字段为stu_sex 添加了注解@Dict(dicDataSource = "stu_sex") 会在字典服务立马查出来对应的text 然后在请求list的时候将这个字典text,已字段名称加_dictText形式返回到前端 * 例输入当前返回值的就会多出一个stu_sex_dictText字段 * { * stu_sex:1, * stu_sex_dictText:"男" * } * 前端直接取值sext_dictText在table里面无需再进行前端的字典转换了 * customRender:function (text) { * if(text==1){ * return "男"; * }else if(text==2){ * return "女"; * }else{ * return text; * } * } * 目前vue是这么进行字典渲染到table上的多了就很麻烦了 这个直接在服务端渲染完成前端可以直接用 * * @param result */ private void parseDictText(Object result) { if (result instanceof PageUtils) { List<JSONObject> items = new ArrayList<>(); PageUtils pageUtils = (PageUtils) result; //循环查找出来的数据 for (Object record : pageUtils.getData()) { ObjectMapper mapper = new ObjectMapper(); String json = "{}"; try { //解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat json = mapper.writeValueAsString(record); } catch (JsonProcessingException e) { log.error("json解析失败" + e.getMessage(), e); } JSONObject item = JSONObject.parseObject(json); //update-begin--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------ //for (Field field : record.getClass().getDeclaredFields()) { for (Field field : ObjConvertUtils.getAllFields(record)) { //update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------ if (field.getAnnotation(Dict.class) != null) { String datasource = field.getAnnotation(Dict.class).dicDataSource(); String text = field.getAnnotation(Dict.class).dicText(); //获取当前带翻译的值 String key = String.valueOf(item.get(field.getName())); //翻译字典值对应的txt String textValue = translateDictValue(datasource, key); // DICT_TEXT_SUFFIX的值为,是默认值: // public static final String DICT_TEXT_SUFFIX = "_dictText"; log.debug(" 字典Val : " + textValue); log.debug(" __翻译字典字段__ " + field.getName() + DICT_TEXT_SUFFIX + ": " + textValue); //如果给了文本名 if (!StringUtils.isEmpty(text)) { item.put(text, textValue); } else { //走默认策略 item.put(field.getName() + DICT_TEXT_SUFFIX, textValue); } } //date类型默认转换string格式化日期 if (field.getType().getName().equals("java.util.Date") && field.getAnnotation(JsonFormat.class) == null && item.get(field.getName()) != null) { SimpleDateFormat aDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName())))); } } items.add(item); } pageUtils.setData(items); } } /** * 翻译字典文本 * * @param datasource * @param key * @return */ private String translateDictValue(String datasource, String key) { //如果key为空直接返回就好了 if (ObjConvertUtils.isEmpty(key)) { return null; } StringBuffer textValue = new StringBuffer(); //分割 key 值 String[] keys = key.split(","); //循环 keys 中的所有值 for (String k : keys) { String tmpValue = null; log.debug(" 字典 key : " + k); if (k.trim().length() == 0) { continue; //跳过循环 } tmpValue = dataItemService.selectByDatasourceKey(datasource, k.trim()); if (tmpValue != null) { if (!"".equals(textValue.toString())) { textValue.append(","); } textValue.append(tmpValue); } } //返回翻译的值 return textValue.toString(); } }
Dict.java
package com.javaxl.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author 小李飞刀 * @site www.javaxl.com * @company * @create 2019-11-24 20:37 * * 专门用于数据字典中的数字转汉字的自定义注解 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Dict { /** * 方法描述: 数据dataSource * @return 返回类型: String */ String dicDataSource(); /** * 方法描述: 这是返回后Put到josn中的文本 key 值 * @return 返回类型: String */ String dicText() default ""; }
PageUtils.java
package com.javaxl.util; import java.io.Serializable; import java.util.List; /** * @author 小李飞刀 * @site www.javaxl.com * @company * @create 2019-11-24 20:36 */ public class PageUtils implements Serializable { private static final long serialVersionUID = 1L; //这是总行数 private long total; //这是保持查询出来的数据 private List<?> data; /** * * @param list 保存数据 * @param total 查到多行数据 */ public PageUtils(List<?> list, long total) { this.data = list; this.total = total; } public long getTotal() { return total; } public void setTotal(int total) { this.total = total; } public List<?> getData() { return data; } public void setData(List<?> data) { this.data = data; } public static long getSerialVersionUID() { return serialVersionUID; } }
ObjConvertUtils.java
package com.javaxl.util; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * @author 小李飞刀 * @site www.javaxl.com * @company * @create 2019-11-24 20:37 */ public class ObjConvertUtils { /** * 获取类的所有属性,包括父类 * * @param object * @return */ public static Field[] getAllFields(Object object) { Class<?> clazz = object.getClass(); List<Field> fieldList = new ArrayList<>(); while (clazz != null) { fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields()))); clazz = clazz.getSuperclass(); } Field[] fields = new Field[fieldList.size()]; fieldList.toArray(fields); return fields; } public static boolean isEmpty(Object object) { if (object == null) { return (true); } if ("".equals(object)) { return (true); } if ("null".equals(object)) { return (true); } return (false); } }
友情提示:
真正的自定义注解去做数据字典的转义,应该在切面类引用缓存技术,比如redis;不然的话每次转义一个数字为汉字,还需要查询一次数据库,性能十分低下;
over......
备案号:湘ICP备19000029号
Copyright © 2018-2019 javaxl晓码阁 版权所有