加载中
KerryLi 2018/08/03 18:15 发布了问题:
KerryLi 2018/06/06 15:35 发布了新博客:
KerryLi 2018/05/15 10:09 发布了新博客:

http://standards-oui.ieee.org/oui/oui.txt

KerryLi 2017/09/08 11:19 回答了问题: 获奖奖品列表

kotlin

@两味真火
合作伙伴
执行这个
# ln -sv /usr/include/fastcommon /usr/local/include/fastcommon
# ln -sv /usr/include/fastdfs /usr/local/include/fastdfs
@凯文加内特
报错信息: 在包含自 /usr/local/src/fastdfs-nginx-module/src/ngx_ht...

写个sql函数,转成时间戳比对

@黄贤达
各位大佬 sql 怎么比对某个日期在不在某段日期区间(不比对年份,只比对日月) 谢谢举个例子 比如 2013-7-...
每天上班没事必来oschina转转
@达尔文
开源已“九”,不忘初心 —— 开源中国九周年特别献礼!2008 年 8 月 31 日,OSChina 网站正式上线...
原因是?
@KerryLi
单表数据, 大概10个字段内每天入此表的数据大概有50w,不需要事务。此表数据高频率更新,插入,读取。数据库选型?

问题解决, 方案 1,如果在springmvc项目中可以配置  事务,和自定义切面的执行顺序

方案2 另起一个其他线程类Thread,实现日志的记录

方案一实现:

xml配置设置事务order

<!-- 配置 Annotation 驱动,扫描@Transactional注解的类定义事务  -->
	<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" order="2"/>
    <!-- MyBatis end -->

自定义横切面设置order

@Component
@Aspect
@Order(1)
public class AppLogAdvice {
	private Logger log=Logger.getLogger(AppLogAdvice.class);
	
	@Autowired
	private AppLogService logService;

	
	private NamedThreadLocal<Long>  startTimeThreadLocal =new NamedThreadLocal<Long>("StopWatch-StartTime");
	
	@Pointcut("@annotation(com.powercn.fcity.common.base.MethodLog)")
	private void pointcut() {}
	
	
	@Around("pointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
		AppLog logEntity=new AppLog();
		long beginTime = System.currentTimeMillis();//1、开始时间
        startTimeThreadLocal.set(beginTime);//线程绑定变量(该数据只有当前请求的线程可见)
		logEntity.setId(UUID.randomUUID().toString().replace("-", ""));
		ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request=attributes.getRequest();
		
		StringBuffer paramStr=new StringBuffer();
		Enumeration<String> nameList=request.getParameterNames();
		while(nameList.hasMoreElements()){
			String name = nameList.nextElement();
			paramStr.append(name).append("=").append(request.getParameter(name)).append("&");
		}
		Map<String, String> map = getMethodLog(point);  
        logEntity.setPath(request.getRequestURI());
        if(paramStr.length()>0){
        	logEntity.setParam(paramStr.substring(0,paramStr.length()-1));
        }
        logEntity.setModule(map.get("module"));
        logEntity.setFunction(map.get("function"));
        Object object = null;
        try{
        	object=point.proceed();
        	logEntity.setStatus("0");
        	logEntity.setRemark("成功");
        	return object;
        }catch(Exception e){
        	e.printStackTrace();
        	logEntity.setStatus("1");
        	logEntity.setRemark("程序出异常");
        	if(e!=null){
        		logEntity.setException(getExceptionTrace(e));
        	}
        }finally{
        	long endTime = System.currentTimeMillis();//1结束时间
    		long time=endTime-startTimeThreadLocal.get();
    		logEntity.setConsumeTime(String.valueOf(time));
    		log.info("Msg:开始写入日志...");
    		logService.addAppLog(logEntity);
    		log.info("Msg:日志写入结束");
		}
        return object;
	}

 

方案二实现如下:

@Component
@Aspect
public class AppLogAdvice {
	private Logger log=Logger.getLogger(AppLogAdvice.class);
	
	@Autowired
	private AppLogService logService;

	
	private NamedThreadLocal<Long>  startTimeThreadLocal =new NamedThreadLocal<Long>("StopWatch-StartTime");
	
	@Pointcut("@annotation(com.kerry.aop.MethodLog)")
	private void pointcut() {}
	
	
	@Around("pointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
		AppLog logEntity=new AppLog();
		long beginTime = System.currentTimeMillis();//1、开始时间
        startTimeThreadLocal.set(beginTime);//线程绑定变量(该数据只有当前请求的线程可见)
		logEntity.setId(UUID.randomUUID().toString().replace("-", ""));
		ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request=attributes.getRequest();
		
		StringBuffer paramStr=new StringBuffer();
		Enumeration<String> nameList=request.getParameterNames();
		while(nameList.hasMoreElements()){
			String name = nameList.nextElement();
			paramStr.append(name).append("=").append(request.getParameter(name)).append("&");
		}
		Map<String, String> map = getMethodLog(point);  
        logEntity.setPath(request.getRequestURI());
        if(paramStr.length()>0){
        	logEntity.setParam(paramStr.substring(0,paramStr.length()-1));
        }
        logEntity.setModule(map.get("module"));
        logEntity.setFunction(map.get("function"));
        Object object = null;
        try{
        	object=point.proceed();
        	logEntity.setStatus("0");
        	logEntity.setRemark("成功");
        	return object;
        }catch(Exception e){
        	e.printStackTrace();
        	logEntity.setStatus("1");
        	logEntity.setRemark("程序出异常");
        	if(e!=null){
        		logEntity.setException(getExceptionTrace(e));
        	}
        	new RuntimeException();
        }finally{
        	long endTime = System.currentTimeMillis();//1结束时间
    		long time=endTime-startTimeThreadLocal.get();
    		logEntity.setConsumeTime(String.valueOf(time));
    		log.info("Msg:开始写入日志...");
//    		logService.addAppLog(logEntity);
    		new LogThread(logService, logEntity).start();
    		log.info("Msg:日志写入结束");
		}
        return object;
	}

这样的话 就会先执行自定义的切面 AppLogAdvice, 在执行spring事务的管理, service异常 service中事务会回滚,切面中日志也会正常记录。

切面执行顺序只是springmvc中的解决方法,但是springboot中如何解决了。 springboot中貌似事务都是自动配置的,如何配置事务切面的order属性呢??

springboot中在切面类上注解@Order(1)  里面数字尽可能下,保证自定义切面先运行。

@KerryLi
在servvice层的某个方法用@transactional开启事务, 也在service的方法用自定义注解开启日...
回复 @KerryLi : 在@around上事务还是不会回滚,用在@AfterThrowing上才可以,,,,,,
@KerryLi
在servvice层的某个方法用@transactional开启事务, 也在service的方法用自定义注解开启日...
通过新启动thread线程运行确实可以,日志正常记录,user也能回滚,,, 总感觉有点笨,这方法..........
@KerryLi
在servvice层的某个方法用@transactional开启事务, 也在service的方法用自定义注解开启日...
切面类不用try catch, 日志都给回滚了,,,
@KerryLi
在servvice层的某个方法用@transactional开启事务, 也在service的方法用自定义注解开启日...

没有更多内容

加载失败,请刷新页面

返回顶部
顶部