手动分页
非mybatis 自动分页
service 层
@Override
public PageInfo<CfLogVo> cfLogList(CfLogQuery cfLogQuery) {
if (StrUtil.isNotBlank(cfLogQuery.getRequest()) && cfLogQuery.getRequest().length() >100){
throw new ServiceException("请求报文长度不能大于100个字符!");
};
if (StrUtil.isNotBlank(cfLogQuery.getResponse()) && cfLogQuery.getResponse().length() >100){
throw new ServiceException("响应报文长度不能大于100个字符!");
};
if (ObjectUtil.isEmpty(cfLogQuery.getBeginTime()))
throw new ServiceException("开始时间不能为空!");
if (ObjectUtil.isEmpty(cfLogQuery.getEndTime()))
throw new ServiceException("结束时间不能为空!");
//PageHelper.startPage(cfLogQuery.getPage(), cfLogQuery.getLimit());
cfLogQuery.setPage((cfLogQuery.getPage() - 1) * cfLogQuery.getLimit());
//Integer listLogsByCount = cfLogDao.findListLogsByCount(cfLogQuery);
Integer listLogsByCount = 1000;
List<CfLogVo> listLogs = cfLogDao.findListLogs(cfLogQuery);
PageInfo pageInfo = new PageInfo<CfLogVo>(listLogs);
pageInfo.setPageNum(cfLogQuery.getPage());
pageInfo.setPageSize(cfLogQuery.getLimit());
pageInfo.setTotal(listLogsByCount == null ? 0 : listLogsByCount);
return pageInfo;
}
maper
<select id="findListLogs" resultType="com.kamowl.kamo.cloud.third.open.vo.CfLogVo" parameterType="com.kamowl.kamo.cloud.third.open.query.report.cf.CfLogQuery">
SELECT * from cf_log
<include refid="where"/>
order by create_time desc
limit ${page},${limit}
</select>
<select id="findListLogsByCount" resultType="integer" parameterType="com.kamowl.kamo.cloud.third.open.query.report.cf.CfLogQuery">
SELECT count(1) from cf_log
<include refid="where"/>
</select>
<sql id="where">
<where>
<if test="type != null and type != ''">
and type = #{type}
</if>
<if test="response != null and response != ''">
and response like concat('%', #{response}, '%')
</if>
<if test="request != null and request != ''">
and request like concat('%', #{request}, '%')
</if>
<if test="url != null and url != ''">
and url like concat('%', #{url}, '%')
</if>
<if test="state != null ">
and state = #{state}
</if>
<if test="beginTime != null">
and create_time>=#{beginTime}
</if>
<if test="endTime != null">
and #{endTime}>=create_time
</if>
</where>
</sql>
事务@Transactional(rollbackFor=Exception.class)
当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。
在项目中,@Transactional(rollbackFor=Exception.class),如果类加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。
在@Transactional注解中如果不配置rollbackFor属性,那么事物只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事物在遇到非运行时异常时也回滚
属性 | 类型 | 描述 |
---|---|---|
value | String | 可选的限定描述符,指定使用的事务管理器 |
propagation | enum: Propagation | 可选的事务传播行为设置 |
isolation | enum: Isolation | 可选的事务隔离级别设置 |
readOnly | boolean | 读写或只读事务,默认读写 |
timeout | int (in seconds granularity) | 事务超时时间设置 |
rollbackFor | Class对象数组,必须继承自Throwable | 导致事务回滚的异常类数组 |
rollbackForClassName | 类名数组,必须继承自Throwable | 导致事务回滚的异常类名字数组 |
noRollbackFor | Class对象数组,必须继承自Throwable | 不会导致事务回滚的异常类数组 |
noRollbackForClassName | 类名数组,必须继承自Throwable | 不会导致事务回滚的异常类名字数组 |
注释权限@PreAuthorize
Spring-Security@PreAuthorize(“hasAuthority(‘’)”)源码分析
连接
Spring-Security@PreAuthorize(“hasAuthority(’’)”)源码分析
@PreAuthorize(“hasAuthority(‘xxx’)”)用来鉴别当前登录用户所拥有的角色是否有xxx权限访问该接口。
点进去看看security是如何来鉴权的。
这里authority即为我们传入的权限,比如prod:create,接下来再看this.hasAnyAuthority如何处理这个权限字符串吧。
翻看源码的话会发现其实hasAnyAuthority方法就在hasAuthority方法的下面,该访问hasAnyAuthorityName了,我们传入的权限字符串(prod:create)就像皮球一样被踢到了hasAnyAuthorityName脚下了~
该方法终于要射门了!
首行为 Set roleSet = this.getAuthoritySet(); 点进去getAuthorityeSet()方法看到
该方法为获取当前用户所拥有角色的所有权限,Collection<? extends GrantedAuthority> userAuthorities = this.authentication.getAuthorities();此行为登录操作时应访问数据库将用户权限放入authentication中,也就是说,这一行将会把该用户所持角色的所有权限都查询出来。
此时我们的鉴权字符串(“prod:create”)被守门员getRoleWithDefaultPrefix()拿下,来看看守门员是怎么守住这球的:
原来是判断一下这球是不是假动作啊,该方法会对传入的(prod:create)进行组装,前面传入的这个defaultRolePrefix为null,所以直接返回role即可,也就是我们一开始传入的“prod:create”。
该比对了,prod:create字符串在权限集合roleSet中,即该用户有访问该接口的权限。
总的来说,鉴权过程为:从数据库中查询出当前登录用户的所有权限并交给security管理;注解@PreAuthorize(“hasAuthority(‘xxx’)”)来判断“xxx”是否在当前登录用户的权限集合中,在则200,不在则403。
@GetMapping("/adm/adminTradeController/detail")
@PreAuthorize("hasAuthority('trade:get:tradePayDetailVo')")
@ApiOperation(value = "后台获取支付详情数据)")
@ApiImplicitParams({
@ApiImplicitParam(name = "tradeId", value = "订单ID", required = true, dataType = "int", example = "0"),
})
@LogAnnotation
public Result<TradePayDetailVo> tradePayDetailVo(@RequestParam("tradeId") Integer tradeId) {
return tradeService.getTradePayDetailVo(tradeId);
}
@PreAuthorize(“hasAuthority(‘trade:get:tradePayDetailVo’)”)
@Component注解的作用
Spring自带的@Component注解及扩展:
@Component:定义Spring管理Bean(也就是将标注@Component注解的类交由spring管理)
@AspectJ风格的切面可以通过@Compenent注解标识其为Spring管理Bean,而@Aspect注解不能被Spring自动识别并注册为Bean,必须通过@Component注解来完成
@Component
@Aspect
@Order(5)
@Slf4j
public class ReportAspect {
@Autowired
private ThirdFeignClient thirdFeignClient;
@Pointcut("@within(com.kamowl.kamo.cloud.third.open.annotation.Report) || @annotation(com.kamowl.kamo.cloud.third.open.annotation.Report)")
public void pointCut() {
}
@AfterReturning(pointcut = "pointCut() && @annotation(report)", returning = "methodResult")
public void doAfterAdvice(JoinPoint joinPoint, Report report, Object methodResult) {
Result result = (Result) methodResult;
ReportChannel[] channels = report.channel();
for (ReportChannel channel : channels) {
thirdFeignClient.upload(assembleReport(channel, report.type(), result.getData() + ""));
}
}
private ReportDto assembleReport(ReportChannel channel, ReportType type, String uniqueId) {
ReportDto reportDto = new ReportDto();
reportDto.setChannel(channel);
reportDto.setType(type);
reportDto.setUniqueId(uniqueId);
return reportDto;
}
}
springboot2 valid @RequestBody @Valid 校验失效
https://blog.csdn.net/xxpxxpoo8/article/details/127551926