Appearance
acuity-annotation 全局注解类
说明
自定义注解
@NotEmptyPattern
表单字段验证:正则表达式
对
javax.validation.constraints.Pattern
注解的增强,用于校验字段的参数不为空时传递的参数是否符合指定的正则表达式。跟 javax.validation.constraints.Pattern 的区别在于: 本类校验时,传递过来的参数为null或者""时,不会校验正则表达式javapublic class UserSaveVO{ // 无论参数是否为空,都直接校验是否满足{regexp} (也可以通过写正则来判断不为空时才校验) @javax.validation.constraints.Pattern(regexp="", message="") private String name; // 当code不为空时,才校验是否满足{regexp} @top.acuity.commons.annotation.constraints.NotEmptyPattern(regexp="", message="") private String code; }
public class UserSaveVO{ // 无论参数是否为空,都直接校验是否满足{regexp} (也可以通过写正则来判断不为空时才校验) @javax.validation.constraints.Pattern(regexp="", message="") private String name; // 当code不为空时,才校验是否满足{regexp} @top.acuity.commons.annotation.constraints.NotEmptyPattern(regexp="", message="") private String code; }
@TenantLine
租户模式为DATASOURCE_COLUMN模式时,将该类标记在Mapper类或方法上,使得通过该Mapper类执行的SQL语句可以自动拼接小租户(默认是 所属某一层级org_id)的条件。
java@Repository // 类上加了此注解,该类下所有方法都会自动拼接租户的条件,包括继承SuperMapper类的方法 @TenantLine public interface BaseEmployeeTestMapper extends SuperMapper<BaseEmployee> { // 标记此注解,并设置为false,表示该方法不需要拼接租户条件 @TenantLine(false) @Select("select * from base_employee where id = #{id}") BaseEmployee get(Long id); }
@Repository // 类上加了此注解,该类下所有方法都会自动拼接租户的条件,包括继承SuperMapper类的方法 @TenantLine public interface BaseEmployeeTestMapper extends SuperMapper<BaseEmployee> { // 标记此注解,并设置为false,表示该方法不需要拼接租户条件 @TenantLine(false) @Select("select * from base_employee where id = #{id}") BaseEmployee get(Long id); }
回显注解
@Echo
用于字典回显、外键回显、枚举回显。
@Echo
注解标记到实体类、VO类的字段,不负责具体的回显逻辑。在某个对象的字段上标记该注解,该字段的值将被主动注入,如:
javaublic class BaseEmployee implements Serializable, EchoVO { // 将数据回显到 echoMap private Map<String, Object> echoMap = MapUtil.newHashMap(); // 岗位状态:回显字典 @Echo(api = EchoApi.DICTIONARY_ITEM_FEIGN_CLASS, dictType = EchoDictType.Base.POSITION_STATUS) private String positionStatus; // 性别:回显枚举 @Echo(api = Echo.ENUM_API) private Sex sex; // 用户:回显用户 @Echo(api = EchoApi.USER_ID_CLASS) private Long userId; } @Echo(api = "dictionaryServiceImpl") private String nation; @Echo(api = "dictionaryApi") private String nation; @Echo(api = "xxx.xxx.xxx.UserApi", beanClass = User.class) private Long userId;
ublic class BaseEmployee implements Serializable, EchoVO { // 将数据回显到 echoMap private Map<String, Object> echoMap = MapUtil.newHashMap(); // 岗位状态:回显字典 @Echo(api = EchoApi.DICTIONARY_ITEM_FEIGN_CLASS, dictType = EchoDictType.Base.POSITION_STATUS) private String positionStatus; // 性别:回显枚举 @Echo(api = Echo.ENUM_API) private Sex sex; // 用户:回显用户 @Echo(api = EchoApi.USER_ID_CLASS) private Long userId; } @Echo(api = "dictionaryServiceImpl") private String nation; @Echo(api = "dictionaryApi") private String nation; @Echo(api = "xxx.xxx.xxx.UserApi", beanClass = User.class) private Long userId;
建议
强烈建议不要对象之间互相依赖,如: User 想要注入 File, File也想注入User
@EchoResult
将该注解标记在service方法上, 调用该方法后,返回值中标记了@Echo 注解的字段将会自动注入属性
TIP
除了@EchoResult注解,还可以通过
echoService.action(new BaseEmployee())
注意
该方法不能写在 Mapper 的方法上。
javapublic class EmployeeServiceImpl { // 标记此注解后,返回值 BaseEmployee 字段上标记了 @Echo 的字段将会回显到echoMap中 @EchoResult public BaseEmployee getById(Long id) { // 查数据库 return baseMapper.getById(id); } }
public class EmployeeServiceImpl { // 标记此注解后,返回值 BaseEmployee 字段上标记了 @Echo 的字段将会回显到echoMap中 @EchoResult public BaseEmployee getById(Long id) { // 查数据库 return baseMapper.getById(id); } }
@WebLog
操作日志注解: 该注解标记在Controller层,用于记录请求接口的操作日志。
java
@WebLog("员工")
public class BaseEmployeeController
@PostMapping("/test")
@WebLog(enabled = false, value = "测试")
public R<List<Long>> test(@RequestBody BaseEmployeeRoleRelSaveVO employeeRoleSaveVO) {
return success(superService.test(employeeRoleSaveVO));
}
@PostMapping("/employeeRole")
@WebLog("给员工分配角色")
public R<List<Long>> saveEmployeeRole(@RequestBody BaseEmployeeRoleRelSaveVO employeeRoleSaveVO) {
return success(superService.saveEmployeeRole(employeeRoleSaveVO));
}
}
@WebLog("员工")
public class BaseEmployeeController
@PostMapping("/test")
@WebLog(enabled = false, value = "测试")
public R<List<Long>> test(@RequestBody BaseEmployeeRoleRelSaveVO employeeRoleSaveVO) {
return success(superService.test(employeeRoleSaveVO));
}
@PostMapping("/employeeRole")
@WebLog("给员工分配角色")
public R<List<Long>> saveEmployeeRole(@RequestBody BaseEmployeeRoleRelSaveVO employeeRoleSaveVO) {
return success(superService.saveEmployeeRole(employeeRoleSaveVO));
}
}
@LoginUser
将该注解标记在Controller层方法的参数SysUser上,为SysUser对象自动注入当前登录人的数据。
- 例1:public void test(@LoginUser SysUser user) // 取BaseContextHandler中的 用户id、账号、姓名、组织id、岗位id等信息
- 例2:public void test(@LoginUser(isRoles = true) SysUser user) //能获取SysUser对象的实时的用户信息和角色信息
- 例3:public void test(@LoginUser(isOrg = true) SysUser user) //能获取SysUser对象的实时的用户信息和组织信息
- 例4:public void test(@LoginUser(isStation = true) SysUser user) //能获取SysUser对象的实时的用户信息和岗位信息
- 例5:public void test(@LoginUser(isFull = true) SysUser user) //能获取SysUser对象的所有信息
- 例6:public void test(@LoginUser(isResource = true) SysUser user) //能获取SysUser对象的实时的用户信息和资源信息
- 缺点1: 不能用于 BaseController 类中的方法
- 缺点2: 不能和@RequesyBody 标记的参数,同时使用
java
public class BaseEmployeeController extends SuperController<BaseEmployeeService, Long, BaseEmployee, BaseEmployeeSaveVO, BaseEmployeeUpdateVO, BaseEmployeePageQuery, BaseEmployeeResultVO> {
// 填充所有的 用户信息
@PostMapping("/save2")
public R<Boolean> save2(@RequestBody @Validated(SuperEntity.Update.class) ExtendMsgSendVO data,
@ApiIgnore @LoginUser(isFull = true) SysUser sysUser) {
return R.success();
}
// 填充用户的员工信息
@PostMapping("/save3")
public R<Boolean> save3(@ApiIgnore @LoginUser(isEmployee = true) SysUser sysUser) { return R.success(); }
// 填充用户基本信息
@PostMapping("/save4")
public R<Boolean> save4(@ApiIgnore @LoginUser(isUser = true) SysUser sysUser) { return R.success(); }
// 填充用户拥有的资源
@PostMapping("/save5")
public R<Boolean> save5(@ApiIgnore @LoginUser(isResource = true) SysUser sysUser) { return R.success(); }
// 填充用户的机构信息
@PostMapping("/save6")
public R<Boolean> save6(@ApiIgnore @LoginUser(isOrg = true) SysUser sysUser) { return R.success(); }
}
public class BaseEmployeeController extends SuperController<BaseEmployeeService, Long, BaseEmployee, BaseEmployeeSaveVO, BaseEmployeeUpdateVO, BaseEmployeePageQuery, BaseEmployeeResultVO> {
// 填充所有的 用户信息
@PostMapping("/save2")
public R<Boolean> save2(@RequestBody @Validated(SuperEntity.Update.class) ExtendMsgSendVO data,
@ApiIgnore @LoginUser(isFull = true) SysUser sysUser) {
return R.success();
}
// 填充用户的员工信息
@PostMapping("/save3")
public R<Boolean> save3(@ApiIgnore @LoginUser(isEmployee = true) SysUser sysUser) { return R.success(); }
// 填充用户基本信息
@PostMapping("/save4")
public R<Boolean> save4(@ApiIgnore @LoginUser(isUser = true) SysUser sysUser) { return R.success(); }
// 填充用户拥有的资源
@PostMapping("/save5")
public R<Boolean> save5(@ApiIgnore @LoginUser(isResource = true) SysUser sysUser) { return R.success(); }
// 填充用户的机构信息
@PostMapping("/save6")
public R<Boolean> save6(@ApiIgnore @LoginUser(isOrg = true) SysUser sysUser) { return R.success(); }
}
java
public class BaseEmployeeController extends SuperController<BaseEmployeeService, Long, BaseEmployee, BaseEmployeeSaveVO, BaseEmployeeUpdateVO, BaseEmployeePageQuery, BaseEmployeeResultVO> {
// 无法在重写父类SaveController的save方法时,添加 @LoginUser
@Override
@PostMapping
public R<BaseEmployee> save(@RequestBody @Validated SaveVO BaseEmployeeSaveVO, @ApiIgnore @LoginUser(isFull = true) SysUser sysUser) {
return R.success();
}
// 不能标记在 @RequestBody注解标记的参数上
@PostMapping("/save2")
public R<Boolean> save2(@ApiIgnore @LoginUser(isFull = true) @RequestBody SysUser sysUser) {
return R.success();
}
}
public class BaseEmployeeController extends SuperController<BaseEmployeeService, Long, BaseEmployee, BaseEmployeeSaveVO, BaseEmployeeUpdateVO, BaseEmployeePageQuery, BaseEmployeeResultVO> {
// 无法在重写父类SaveController的save方法时,添加 @LoginUser
@Override
@PostMapping
public R<BaseEmployee> save(@RequestBody @Validated SaveVO BaseEmployeeSaveVO, @ApiIgnore @LoginUser(isFull = true) SysUser sysUser) {
return R.success();
}
// 不能标记在 @RequestBody注解标记的参数上
@PostMapping("/save2")
public R<Boolean> save2(@ApiIgnore @LoginUser(isFull = true) @RequestBody SysUser sysUser) {
return R.success();
}
}
@IgnoreResponseBodyAdvice
忽略全局响应包装,若系统启用了AbstractGlobalResponseBodyAdvice类,系统会将Controller层所有方法的返回值自动包装为
R
对象。该注解用于局部禁用此功能。javapublic class CaptchaController { /* * 若服务通过配置,启用了AbstractGlobalResponseBodyAdvice类,默认情况下Controller层所有的方法都会按照 R 的格式返回 */ @GetMapping(value = "/captcha", produces = "image/png") @IgnoreResponseBodyAdvice public void captcha(@RequestParam(value = "key") String key, HttpServletResponse response) throws IOException { this.captchaService.createImg(key, response); } // 虽然方法只返回了User对象,但前端接收到的实际上是 R.success(user) @GetMapping(value = "/test") public User test() throws IOException { return new User().setId(1); } }
public class CaptchaController { /* * 若服务通过配置,启用了AbstractGlobalResponseBodyAdvice类,默认情况下Controller层所有的方法都会按照 R 的格式返回 */ @GetMapping(value = "/captcha", produces = "image/png") @IgnoreResponseBodyAdvice public void captcha(@RequestParam(value = "key") String key, HttpServletResponse response) throws IOException { this.captchaService.createImg(key, response); } // 虽然方法只返回了User对象,但前端接收到的实际上是 R.success(user) @GetMapping(value = "/test") public User test() throws IOException { return new User().setId(1); } }
javapublic class AbstractGlobalResponseBodyAdvice implements ResponseBodyAdvice<Object> { @Override public boolean supports(MethodParameter methodParameter, Class aClass) { // 类上如果被 IgnoreResponseBodyAdvice 标识就不拦截 if (methodParameter.getDeclaringClass().isAnnotationPresent(IgnoreResponseBodyAdvice.class)) { return false; } // 方法上被标注也不拦截 return !Objects.requireNonNull(methodParameter.getMethod()).isAnnotationPresent(IgnoreResponseBodyAdvice.class); } @Override public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { if (o == null) { return null; } if (o instanceof R) { return o; } return R.success(o); } }
public class AbstractGlobalResponseBodyAdvice implements ResponseBodyAdvice<Object> { @Override public boolean supports(MethodParameter methodParameter, Class aClass) { // 类上如果被 IgnoreResponseBodyAdvice 标识就不拦截 if (methodParameter.getDeclaringClass().isAnnotationPresent(IgnoreResponseBodyAdvice.class)) { return false; } // 方法上被标注也不拦截 return !Objects.requireNonNull(methodParameter.getMethod()).isAnnotationPresent(IgnoreResponseBodyAdvice.class); } @Override public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { if (o == null) { return null; } if (o instanceof R) { return o; } return R.success(o); } }
json{ "code": 0, // 状态码 0表示请求成功 其他请求失败 "data": { // 将controller层的返回值包装到data字段 }, "errorMsg": "", //错误消息 "extra": {}, // 扩展数据 "isSuccess": true, // 是否请求成功 "msg": "", // 响应消息 "path": "", // 访问失败时的请求路径 "timestamp": 0 // 后端响应时的时间戳 }
{ "code": 0, // 状态码 0表示请求成功 其他请求失败 "data": { // 将controller层的返回值包装到data字段 }, "errorMsg": "", //错误消息 "extra": {}, // 扩展数据 "isSuccess": true, // 是否请求成功 "msg": "", // 响应消息 "path": "", // 访问失败时的请求路径 "timestamp": 0 // 后端响应时的时间戳 }