本篇博客主要聊聊自定义注解在项目中的应用,自定义注解用来做系统监控日志,这个用法已经烂大街了,无法让面试官眼前一亮的感觉。
项目开发中数据字典使用场景非常多,使用数据字典有一点非常的不方便,那就是数据库中存放的是数字,而实际页面上展示的却是汉字;那么这也就造成了,每次做页面展示的时候都需要给数字进行转义,将其转义成汉字内容展示到页面,而转换的过程过于繁琐;
咱们的自定义注解可以完美的解决这一问题;
浏览器输入:http://localhost:8080/student/listPager 测试
最后浏览器访问的效果图
小李飞刀_解决方案
小李飞刀_解决方案
当然,也可以不走默认规则,xxx就是在类属性上的自定义注解的属性值
小李飞刀_解决方案
相关的pom依赖
com.alibaba fastjson 1.2.4逆向工程生成实体类、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 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 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 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 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 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…
来源:CSDN
作者:冬.
链接:https://blog.csdn.net/qq_45174759/article/details/103883848