spring 之 Listener的异步调用

关于listener的原理我这里就不过多叙述了,大家百度一下,一大堆。

我写一个实际案例:(代码非常简单,很多主要是业务的,我就没有删除,不要觉得麻烦,很简单)

情景描述:我监听到一个事件后,想让监听器里面延时10秒执行一些操作,但是controller继续执行自己的代码,返回视图层。

本人先是用拦截器。(只贴出来相关的配置)

先来spring核心容器的配置

        <!-- 拦截器配置,拦截顺序:先执行后定义的,排在第一位的最后执行。-->
	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="${adminPath}/**" />
			<mvc:exclude-mapping path="${adminPath}/"/>
			<mvc:exclude-mapping path="${adminPath}/login"/>
			<mvc:exclude-mapping path="${adminPath}/sys/menu/tree"/>
			<mvc:exclude-mapping path="${adminPath}/sys/menu/treeData"/>
			<mvc:exclude-mapping path="${adminPath}/oa/oaNotify/self/count"/>
			<bean class="com.thinkgem.jeesite.modules.sys.interceptor.LogInterceptor" />
		</mvc:interceptor>
		<!-- finebi拦截器 拦截user和role里面的save方法 -->
		<mvc:interceptor>
			<mvc:mapping path="${adminPath}/sys/user/save" />
			<mvc:mapping path="${adminPath}/sys/role/save" />
			<bean class="com.thinkgem.jeesite.modules.sys.interceptor.FineBIInterceptor" />
		</mvc:interceptor>
	</mvc:interceptors>
下面是拦截器的内容

package com.thinkgem.jeesite.modules.sys.interceptor;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.thinkgem.finebi.entity.Curep;
import com.thinkgem.finebi.service.CurepService;
import com.thinkgem.finebi.service.CustomRoleService;
import com.thinkgem.finebi.utils.FineBIUtils;
import com.thinkgem.jeesite.common.service.BaseService;
import com.thinkgem.jeesite.modules.sys.dao.MenuDao;
import com.thinkgem.jeesite.modules.sys.dao.RoleDao;
import com.thinkgem.jeesite.modules.sys.entity.Menu;
import com.thinkgem.jeesite.modules.sys.entity.Role;

/**
 * @description 描述:FineBI拦截器,拦截user和role controller里面的save方法
 * @author 作者:siqiangming
 * @date 创建时间:2017年8月9日 下午2:32:31
 * @edit 修改时间:
 */
public class FineBIInterceptor extends BaseService implements HandlerInterceptor {
	
	@Autowired
	private RoleDao roleDao;
	@Autowired
	private MenuDao menuDao;
	@Resource
	private CurepService curepService;//FineBI自定义角色权限
	@Resource
	private CustomRoleService customRoleService;//FineBI自定义角色
	
	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		
	}

	@Override
	public void afterCompletion(HttpServletRequest request,HttpServletResponse response, 
			Object handler, Exception ex) throws Exception {
		HandlerMethod  HandlerMethod = (HandlerMethod)handler;
		MethodParameter[] methodParameters = HandlerMethod.getMethodParameters();//获取请求参数数组
		List<String> list = new ArrayList<String>();
		for (MethodParameter methodParameter : methodParameters) {
			list.add(methodParameter.getParameterName());
		}
		System.out.println("本次拦截请求参数============="+list.toString());
		//因为FineBI每隔10秒同步一次
                Thread.sleep(10000);
		//如果是拦截的user的save方法 调用给角色赋予权限的方法
		if (list.indexOf("user") > -1) {
	    	String[] roleIdArray = request.getParameterValues("roleIdList");
	    	List<String> roleIdList = Arrays.asList(roleIdArray);
	        System.out.println(roleIdList+"------------");
	        Iterator<String> it = roleIdList.iterator();
			while (it.hasNext()) {
				Role role = roleDao.get(it.next());
				insertFineBIRoleMenu(role.getName(), role.getMenuList());
			}
		}
		//如果是拦截的role的save方法 调用给角色赋予权限的方法
		if (list.indexOf("role") > -1) {
			String id = request.getParameter("id");
			Role role = roleDao.get(id);
			if (role != null) {
				insertFineBIRoleMenu(role.getName(), role.getMenuList());
			}
		}
		FineBIUtils.refreshCache();//调用FineBI接口刷新缓存
	}
	
	/**
	 * @description 描述:同时将角色的权限添加到finebi数据库
	 * @author 作者:siqiangming
	 * @date 创建时间:2017年8月8日 下午7:34:54
	 * @edit 修改时间:
	 * @parameter 参数:角色id,菜单list
	 */
	public void insertFineBIRoleMenu(String name,List<Menu> menuList){
		Integer roleId = customRoleService.getRoleIdByName(name);
		if(roleId != null){
			deleteFineBIRoleMenu(name);
			if (menuList.size() > 0){
				//遍历角色的权限菜单
				Iterator<Menu> it = menuList.iterator();
				while(it.hasNext()){
					Menu menu = menuDao.get(it.next().getId());
					//查询FineBI中菜单对应的id
					Integer entryId = curepService.getEntryIdByName(menu.getName());
					if(entryId == null){
						continue;
					}
					Curep curep = new Curep(roleId, 7, entryId, 1, 1, 1);
					//检查是否存在这条记录
					if(curepService.checkIfExistCurep(curep)){
						continue;
					}
					curepService.save(curep);
				}
			}
		}
		
	}
	/**
	 * @description 描述:删除FineBI中的角色权限
	 * @author 作者:siqiangming
	 * @date 创建时间:2017年8月8日 下午7:35:37
	 * @edit 修改时间:
	 * @parameter 参数:角色id
	 */
	public void deleteFineBIRoleMenu(String name){
		Integer roleId = customRoleService.getRoleIdByName(name);
		if(roleId != null){
			curepService.deleteCurep(roleId);
			System.out.println(name+":角色的finebi的角色权限已经删除");
		}
	}

}
结果发现页面操作也要等10秒钟,这样的话,太影响了。

百度无数,没有找到解决办法。自己想的是异步调用,没有找到类似的案例。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

果断抛弃使用监听器。

监听器简单说一下:

1、事件    继成一个ApplicationEvent类

2、事件监听者      实现一个ApplicationListener<RoleEvent>接口,接口监听事件,或者集成他的实现类。

3、事件发布者     也就是事件的触发者,监听者怎么知道事件产生呢,就是通过他。


好了,废话不多说了,贴出代码

事件

package com.thinkgem.jeesite.modules.sys.listener;

import java.util.List;

import org.springframework.context.ApplicationEvent;

import com.thinkgem.jeesite.modules.sys.entity.Role;

/**
 * @description 描述:事件
 * @author 作者:siqiangming
 * @date 创建时间:2017年8月11日 下午3:05:44
 * @edit 修改时间:
 */

public class RoleEvent extends ApplicationEvent {
	private static final long serialVersionUID = 1L;
	
	private List<Role> roleList;
	private Role role;
	
	public RoleEvent(Object source, List<Role> roleList) {
		super(source);
		this.roleList = roleList;
		System.out.println("我是保存用户的时候。。。");
	}
	
	public RoleEvent(Object source, Role role) {
		super(source);
		this.role = role;
		System.out.println("我是保存角色的时候。。。");
	}

	public List<Role> getRoleList() {
		return roleList;
	}

	public void setRoleList(List<Role> roleList) {
		this.roleList = roleList;
	}

	public Role getRole() {
		return role;
	}

	public void setRole(Role role) {
		this.role = role;
	}

}

监听者

package com.thinkgem.jeesite.modules.sys.listener;

import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import com.thinkgem.finebi.entity.Curep;
import com.thinkgem.finebi.service.CurepService;
import com.thinkgem.finebi.service.CustomRoleService;
import com.thinkgem.finebi.utils.FineBIUtils;
import com.thinkgem.jeesite.modules.sys.entity.Menu;
import com.thinkgem.jeesite.modules.sys.entity.Role;
import com.thinkgem.jeesite.modules.sys.service.SystemService;

/**
 * @description 描述:事件监听者
 * @author 作者:siqiangming
 * @date 创建时间:2017年8月11日 下午3:14:21
 * @edit 修改时间:
 */
@Component
public class RoleListener implements ApplicationListener<RoleEvent> {

	private Logger logger = Logger.getLogger(RoleListener.class);
	@Resource
	private SystemService systemService;
	@Resource
	private CurepService curepService;//FineBI自定义角色权限
	@Resource
	private CustomRoleService customRoleService;//FineBI自定义角色
	
	@Override
	public void onApplicationEvent(RoleEvent event) {
		logger.debug("我监听到----------事件发生");
		try {
			Thread.sleep(10000);
			logger.debug("我睡眠了----------ok");
		} catch (InterruptedException e) {
			e.printStackTrace();
			logger.debug("我睡眠了----------报错");
		}
		List<Role> roleList = event.getRoleList();
		if (roleList != null && roleList.size() >0) {
			logger.debug("我监听到----------"+roleList.toString());
			Iterator<Role> it = roleList.iterator();
			while (it.hasNext()) {
				Role role = systemService.getRole(it.next().getId());
				insertFineBIRoleMenu(role.getName(), role.getMenuList());
			}
		}
		Role role = event.getRole();
		if (role != null) {
			logger.debug("我监听到----------"+role.toString());
			insertFineBIRoleMenu(role.getName(), role.getMenuList());
		}
		FineBIUtils.refreshCache();//调用FineBI接口刷新缓存
	}

	/**
	 * @description 描述:同时将角色的权限添加到finebi数据库
	 * @author 作者:siqiangming
	 * @date 创建时间:2017年8月8日 下午7:34:54
	 * @edit 修改时间:
	 * @parameter 参数:角色id,菜单list
	 */
	public void insertFineBIRoleMenu(String name,List<Menu> menuList){
		Integer roleId = customRoleService.getRoleIdByName(name);
		if(roleId != null){
			deleteFineBIRoleMenu(name);
			if (menuList.size() > 0){
				//遍历角色的权限菜单
				Iterator<Menu> it = menuList.iterator();
				while(it.hasNext()){
					Menu menu = systemService.getMenu(it.next().getId());
					//查询FineBI中菜单对应的id
					Integer entryId = curepService.getEntryIdByName(menu.getName());
					if(entryId == null){
						continue;
					}
					Curep curep = new Curep(roleId, 7, entryId, 1, 1, 1);
					//检查是否存在这条记录
					if(curepService.checkIfExistCurep(curep)){
						continue;
					}
					curepService.save(curep);
				}
			}
		}
		
	}
	/**
	 * @description 描述:删除FineBI中的角色权限
	 * @author 作者:siqiangming
	 * @date 创建时间:2017年8月8日 下午7:35:37
	 * @edit 修改时间:
	 * @parameter 参数:角色id
	 */
	public void deleteFineBIRoleMenu(String name){
		Integer roleId = customRoleService.getRoleIdByName(name);
		if(roleId != null){
			curepService.deleteCurep(roleId);
			System.out.println(name+":角色的finebi的角色权限已经删除");
		}
	}
}
发布者

package com.thinkgem.jeesite.modules.sys.listener;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import com.thinkgem.jeesite.modules.sys.entity.Role;

/**
 * @description 描述:事件发布者
 * @author 作者:siqiangming
 * @date 创建时间:2017年8月11日 下午3:16:52
 * @edit 修改时间:
 */
@Component
public class RoleEventpPublisher {

	@Autowired
	private ApplicationContext applicationContext;
	
	public void publishEventByRole(Role role){
		applicationContext.publishEvent(new RoleEvent(this, role));
	}
	
	public void publishEventByUser(List<Role> roleList){
		applicationContext.publishEvent(new RoleEvent(this, roleList));
	}
}
到这里,是否可以了呢,当然不行了,你得有人去发布,或者说有地方调用他。

因为代码太多我只拿出来了一部分,先注入发布者

	@Autowired
	private RoleEventpPublisher publisher;//事件发布者
		if (StringUtils.isNotBlank(user.getId())){
			// 更新用户与角色关联
			userDao.deleteUserRole(user);
			if (user.getRoleList() != null && user.getRoleList().size() > 0){
				userDao.insertUserRole(user);
				//TODO 发布事件
				publisher.publishEventByUser(user.getRoleList());
			}else{
				throw new ServiceException(user.getLoginName() + "没有设置角色!");
			}
			// 将当前用户同步到Activiti
			saveActivitiUser(user);
			// 清除用户缓存
			UserUtils.clearCache(user);
//			// 清除权限缓存
//			systemRealm.clearAllCachedAuthorizationInfo();
		}

OK,到这里完事,但是这是同步的,结果和拦截器是一样的。

干货来了,看下嘛的重点,在spring核心容器配置下面代码,其他不用更改。

   <!-- 异步事件处理  20170811-->
	<bean id="applicationEventMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster">
		<!-- 注入任务执行器 这样就实现了异步调用 (缺点是全局的,要么全异步,要么全同步,删除这个属性既是同步) -->
		<property name="taskExecutor" ref="coreTaskExecutor" />
	</bean>
	<!-- 20170811 -->
	<bean id="coreTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
		<property name="corePoolSize" value="10"/><!-- 核心线程数 -->  
		<property name="maxPoolSize" value="20"/><!-- 最大线程数 --> 
		<property name="queueCapacity" value="25"/><!-- 队列最大长度 -->
		<property name="threadNamePrefixSet" value="weiqiao-taskExecutor"/><!-- 线程名前缀集主要用来打印日志区分方便  -->
	</bean>

到这里才是真正的异步调用,将结果发图上来。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值