一、值域校验
model中添加标签
@MasterValidateLabel(objectCd=ObjectCd.EQU_TYPE) Private String typeCd; |
二、基础模型数据初始化
VO配置
新增的VO配置
import java.util.Date; @ApiModelProperty(value="createdByCd", notes="创建者编码",hidden=false) private String createdByCd; @ApiModelProperty(value="createdTime", notes="创建时间",hidden=false) private Date createdTime; public Date getCreatedTime() { return createdTime; } public void setCreatedTime(Date createdTime) { this.createdTime = createdTime; } public String getCreatedByCd() { return createdByCd; } public void setCreatedByCd(String createdByCd) { this.createdByCd = createdByCd; } |
修改的VO配置
import java.util.Date; @ApiModelProperty(value="lastUpdatedByCd", notes="更新者编码",hidden=false) private String lastUpdatedByCd; @ApiModelProperty(value="lastUpdatedTime", notes="更新时间",hidden=false) private Date lastUpdatedTime; public String getLastUpdatedByCd() { return lastUpdatedByCd; } public void setLastUpdatedByCd(String lastUpdatedByCd) { this.lastUpdatedByCd = lastUpdatedByCd; } public Date getLastUpdatedTime () { return lastUpdatedTime; } public void setLastUpdatedTime (Date lastUpdatedTime) { this. lastUpdatedTime = lastUpdatedTime; } |
1.1.1.1.2 Dao层Mapper配置
新增类型
@BaseModelLabel(value=BaseModelLabel.REGISTER) int createWard(PlcWardCreateVo plcWardCreateVo); |
修改类型
@BaseModelLabel(value=BaseModelLabel.UPDATE) boolean alter(PlcWard plcWard); |
1.1.1.1.3 mappers的Mapper使用
创建类型
<if test="createdByCd != null" > #{createdByCd,jdbcType=VARCHAR}, </if> <if test="createdTime != null" > #{createdTime,jdbcType=TIMESTAMP}, </if> |
更新类型
<if test=" lastUpdatedByCd!= null" > #{ lastUpdatedByCd,jdbcType=VARCHAR}, </if> <if test=" lastUpdatedTime!= null" > #{ lastUpdatedTime,jdbcType=TIMESTAMP}, </if> |
三、日志记录
1.1.1.1 依赖xxx-framework-sdk包
<!-- sdk --> <dependency> <groupId>com.xxx.mdd</groupId> <artifactId>mdd-framework</artifactId> <version>1.0.0</version> </dependency> |
1.1.1.2 配置logback-spring.xml
在需要使用日志的服务项目里面,日志文件例子配置如下:
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds"> <springProperty scope="context" name="logPath" source="log.path"/> <springProperty scope="context" name="serverIp" source="spring.cloud.client.hostname"/> <springProperty scope="context" name="serverPort" source="server.port"/> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>[LSV/01][%p][%d{yyyy-MM-dd'T'HH:mm:ss.SSS}]%m%n </pattern> </encoder> </appender> <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${logPath}${serverIp}_${serverPort}.log</file> <encoder> <pattern>[LSV/01][%p][%d{yyyy-MM-dd'T'HH:mm:ss.SSS}]%m%n</pattern> </encoder> <!-- 日志滚动格式 按照时间、大小 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>${logPath}${serverIp}_${serverPort}_%d{yyyyMMdd}_%i.log </FileNamePattern> <MaxHistory>30</MaxHistory> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> </appender> <!-- log4mybatis --> <logger name="jdbc.sqltiming" level="DEBUG" /> <logger name="com.ibatis" level="DEBUG" /> <logger name="com.ibatis.common.jdbc.SimpleDataSource" level="DEBUG" /> <logger name="com.ibatis.common.jdbc.ScriptRunner" level="DEBUG" /> <logger name="com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate" level="DEBUG" /> <logger name="java.sql.Connection" level="DEBUG" /> <logger name="java.sql.Statement" level="DEBUG" /> <logger name="java.sql.PrepareStatement" level="DEBUG" /> <logger name="java.sql.ResultSet" level="DEBUG" /> <logger name="com.xxx.udp.framework.rpc.common.bytecode" level="DEBUG" /> <logger name="com.xxx.udp.framework.rpc.proxy" level="DEBUG" /> <logger name="com.xxx.xxx" level="INFO" /> <root level="WARN"> <appender-ref ref="console" /> <appender-ref ref="file" /> </root> </configuration> |
1.1.1.3 配置中心增加配置
配置中心增加配置如下
#日志logpath log.path: ./logs/${spring.application.name}
如果需要在开发服务器、测试服务器、生产服务器等非调试环境输出正常日志时,需要增加
1.1.1.4 本地测试时开启日志配置
本地测试时本地日志输出需要在本地的application.yml中增加
logback-spring.xml文件同时修改本地的logPath的source由log.path修改为log.path.local。本文件在本地修改的内容,不需要提交道服务器。
<springProperty scope="context" name="logPath" source="log.path.local"/> |
1.1.1.5 异常日志记录
1.1.1.5.1 前端领域服务书写说明
在书写接口时,在controller方法上增加标签
@RequestMapping(value = "/frequency/{code}", method = RequestMethod.GET) @InterfaceApiLabel(value="mst_0001",description="根据频率编码查询频率详细信息") public Result<MstFrequencyVO> searchByCode(@PathVariable String code, @RequestHeader HttpHeaders headers){ int i=1/0;//发生异常自动捕捉 // 根据频率编码查询频率的详细信息 MstFrequencyVO mstFrequency = mstFrequencyService.searchByCode(code); // 将查询结果返回 return new Result<MstFrequencyVO>("0", "查询成功", mstFrequency); } |
value是接口的编码;description为方法的描述。
1.1.1.6 正常日志记录
1.1.1.6.1 前端领域服务书写说明
@RequestMapping(value = "/frequency/{code}", method = RequestMethod.GET) @InterfaceApiLabel(value="mst_0001",description="根据频率编码查询频率详细信息") public Result<MstFrequencyVO> searchByCode(@PathVariable String code, @RequestHeader HttpHeaders headers){ int i=1/0; // 根据频率编码查询频率的详细信息 MstFrequencyVO mstFrequency = mstFrequencyService.searchByCode(code); // 将查询结果返回 return new Result<MstFrequencyVO>("0", "查询成功", mstFrequency); } |
前端只需要书写@InterfaceApiLabel(value="mst_0001",description="根据频率编码查询频率详细信息")标签就可以自动记录详尽的日志信息;
四、参数校验
在注册或者查询时,经常遇到需要校验参数是否为空、数值类型字段的范围、日期格式、正则表达式、邮箱等校验,在写java代码时,需要写大量的代码,带来很多工作量,现在可以通过切面的方式统一拦截,大大提高了开发效率。
Vo标签注解
校验参数是否为空:在vo字段前加@NotBlank(message="10001")
数值类型字段的范围:在vo字段前加@Size(min=3,max=10,message="10002,3,10")
日期格式化:在vo字段前加@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
正则表达式:在vo字段前加
@Pattern(regexp="^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[A-Za-z])$",message="10003")
邮箱:在vo字段前加@Email(message="10004")
message为消息的编码。
示例:
package com.xxx.yyy.demo.vo; import java.util.Date; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; import org.hibernate.validator.constraints.Email; import org.hibernate.validator.constraints.NotBlank; import com.fasterxml.jackson.annotation.JsonFormat; import com.xxx.yyy.sdk.bean.PageBean; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @ApiModel(value="QueryCustParam",description="查询参数条件") public class QueryCustParam{ @ApiModelProperty(value="客户id",notes="客户id") private Long id; @ApiModelProperty(value="客户类型",notes="客户类型",hidden=true) private Integer typeId; @NotBlank(message="10001") @Size(min=3,max=10,message="10002,3,10") @ApiModelProperty(value="编码",notes="客户编码",hidden=true) private String code; @ApiModelProperty(value="名称",notes="客户名称") private String name; @ApiModelProperty(value="描述",notes="客户描述",hidden=true) private String des; @ApiModelProperty(value="性别id",notes="客户性别id") private Integer sexId; @ApiModelProperty(value="出生日期",notes="客户出生日期",dataType="Date") @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") private Date birthday; @ApiModelProperty(value="身份证号",notes="客户身份证号") @Pattern(regexp="^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[A-Za-z])$",message="10003") private String idCardNo; @ApiModelProperty(value="电子邮箱",notes="客户电子邮箱") @Email(message="10004") private String email;
public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Integer getTypeId() { return typeId; } public void setTypeId(Integer typeId) { this.typeId = typeId; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDes() { return des; } public void setDes(String des) { this.des = des; } public Integer getSexId() { return sexId; } public void setSexId(Integer sexId) { this.sexId = sexId; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getIdCardNo() { return idCardNo; } public void setIdCardNo(String idCardNo) { this.idCardNo = idCardNo; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } } |
五、编码转名称
有很多业务领域需要访问主数据领域进行code转name的工作,这项工作需要大量的重复调用服务以及大段的代码赋值的工作,给开发者带来了大量的工作量,因此采用切面的方式,在vo中增加标签,就可以极大地提高开发效率。
Code2Name使用
使用步骤:
1、在model项目中使用路径为com.xxx开头而且vo或model结尾的路径的vo对象
com.xxx.yyy. plc.vo或com.xxx.yyy.plc.model的
2、Vo字段上增加标签@Code2NameLabel(objectCd=ObjectCd.SEX,target="sexNm")
@Code2NameLabel为被转化的字段标签、objectCd=ObjectCd.SEX为对象编码、target="sexNm"为转化目标字段名称
3、code2name需要增convertcode=true;在返参对象Result里面赋值,则进行转换;
4、vo书写样例:
package com.xxx.yyy.usr.vo; import java.util.List; import com.xxx.yyy.sdk.cache.Code2NameLabel; import com.xxx.yyy.sdk.constants.ObjectCd; import io.swagger.annotations.ApiModel; @ApiModel(value="UsrCustomerVO",description="客户信息") public class UsrCustomerVO { private String code; private String name;
@Code2NameLabel(objectCd=ObjectCd.SEX,target="sexNm") private String sexCd; private String sexNm; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSexCd() { return sexCd; } public void setSexCd(String sexCd) { this.sexCd = sexCd; } public String getSexNm() { return sexNm; } public void setSexNm(String sexNm) { this.sexNm = sexNm; } } |
六、通用工具类编程
Boolean flag=PatternUtil.isTelphone("15810357012")
1、通用工具
序号 | 类别 | 类名 | 名称 |
---|---|---|---|
1 | 日期 | DateUtil | 日期工具类 |
2 | 日期 | DateUtils | 日期工具类 |
3 | 文件操作 | BufferedImageUtil | 图像处理工具类 |
4 | 文件操作 | ByteUtil | 图像字节工具类 |
5 | 文件操作 | ValidateCodeUtils | 生成验证码工具类 |
6 | 文件操作 | VerificationCodeTool | 汉字加减乘除验证码生成工具 |
7 | Java对象 | DesensitizedUtils | 脱敏工具类 |
8 | Java对象 | HanToWB | 汉字转五笔工具类 |
9 | Java对象 | MapUtils | map操作工具类 |
10 | Java对象 | ObjectUtils | object操作工具类 |
11 | Java对象 | PatternUtil | 正则表达式工具类 |
12 | Java对象 | Pyjc | 拼音简写工具类 |
13 | Java对象 | StringUtil | 字符串工具类 |
14 | Java对象 | StringUtils | 字符串工具类 |
15 | Java对象 | TranslationSpcilStr | 字符串转译工具类 |
16 | Java对象 | VoPoConverter | 对象转换工具类 |
17 | log日志 | LogUtil | 日志操作工具类 |
18 | os | IPUtil | IP操作工具类 |
19 | poi | HuToolExcelUtils | excel操作工具类 |
20 | poi | ExcelUtils | excel操作工具类 |
21 | 安全 | Base64Util | Base64对称加密工具类 |
22 | 安全 | CryptAES | AES加解密工具类 |
23 | 安全 | DesUtil | DES加解密工具类 |
24 | 安全 | MD5Util | MD5加密工具类 |
25 | 安全 | RSAUtil | RSA加解密工具类 |
26 | url | UrlUtil | URL操作工具类 |
2、redis编程规范
redis工具类
序号 | 名称 | 说明 |
---|---|---|
1 | RedisKVUtil | redis键值对缓存服务工具类 |
2 | RedisHashUtil | redis的hash缓存服务工具类 |
yml文件配置
mdd: redis: util: host: xxx //主数据服务器地址 port: 6379 //主数据redis默认端口号 timeout: 3000 database: 0 //redis数据库组 |
---|
3、ES编程规范
搜索引擎(ElastcSearch)
序号 | 名称 | 说明 |
---|---|---|
1 | EsUtil | es操作工具类 |
yml文件配置
mdd: elasticsearch: host: 10.154.76.200 port: 9200 scheme: http |
---|
4、MongoDb编程规范
mongoDb
序号 | 名称 | 说明 |
---|---|---|
1 | MongoUtil | mongo操作工具类 |
yml配置文件
mdd: mongo: userName: dnName: userPw: host: port: |
---|
七、系统公共Bean
Result
package com.xxx.mdd.framework.core.bean; import com.xxx.mdd.framework.core.message.MessageReader; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; /** * * @ClassName: Result * @Description: 统一返回消息机制 * @date 2017年4月12日 下午8:41:57 * * @param <T> */ @ApiModel(description = "结果对象") public class Result<T> { @ApiModelProperty(name = "code" , value = "编码") private String code; @ApiModelProperty(name = "msg" , value = "消息") private String msg; @ApiModelProperty(name = "pager" , value = "分页对象") private PageBean pager; @ApiModelProperty(name = "data" , value = "数据结果对象") private T data; @ApiModelProperty(name = "throwable" , value = "异常信息") private String throwable; @ApiModelProperty(name = "desensitized" , value = "脱敏标志") private String desensitized; @ApiModelProperty(name = "convertCode" , value = "主数据转换标志") private Boolean convertCode; public Result() { } /** * 构造器 * @param code 返回编码 */ public Result(String code) { this.code = code; this.msg = MessageReader.getMessageReader().getPropertie(code); } /** * 构造器 * @param code 返回编码 * @param data 返回的数据 */ public Result(String code, T data){ this(code); this.data = data; } //入参为编码、消息、消息体 public Result(String code, String msg, T data) { this.code=code; this.msg=msg; this.data = data; } //入参为分页信息、编码、消息、消息体 public Result(String code, String msg, T data, PageBean pager){ this(code, msg, data); this.pager = pager; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; } public String getThrowable() { return throwable; } public void setThrowable(String throwable) { this.throwable = throwable; } public PageBean getPager() { return pager; } public void setPager(PageBean pager) { this.pager = pager; } public String getDesensitized() { return desensitized; } public void setDesensitized(String desensitized) { this.desensitized = desensitized; } public Boolean getConvertCode() { return convertCode; } public void setConvertCode(Boolean convertCode) { this.convertCode = convertCode; } } |
---|
PageBean