EJB3.0变通实现定时任务quartz,schedule ,task,EJB3.0注入Quartz无法注入,注入失败,NullpiontException

本来在EJB框架中引入了quartz-scheduler

		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>2.1.7</version>
		</dependency>


创建了任务类,

/**
 * 定时任务管理类
 * @Author hithedy
 * @Date   2014年7月24日
 * @Time   下午1:43:37
 */
public class QuartzUtil {
	private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory();
	private static String JOB_GROUP_NAME = "CH_W_CMS_JOB_GROUP";
	private static String TRIGGER_GROUP_NAME = "CH_W_CMS_TRIGGER_GROUP";

	/**
	 * 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名
	 *
	 * @param jobName
	 *            任务名
	 * @param jobClass
	 *            任务
	 * @param time
	 *            时间设置,参考quartz说明文档
	 * @throws SchedulerException
	 * @throws ParseException
	 */
	public static void addJob(String jobName, String jobClass, String cronExpression) {
		try {
			Scheduler sched = gSchedulerFactory.getScheduler();
			@SuppressWarnings("unchecked")
			JobDetail jobDetail = newJob((Class<Job>)Class.forName(jobClass))
            .withIdentity(jobName, JOB_GROUP_NAME)
            .build();
			// 触发器
			CronTrigger trigger =newTrigger()
            .withIdentity(jobName+"_tigger", TRIGGER_GROUP_NAME)
            .withSchedule(cronSchedule(cronExpression))
            .build();
			
			sched.scheduleJob(jobDetail, trigger);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	/**
	 * 启动所有定时任务
	 */
	public static void startJobs() {
		try {
			Scheduler sched = gSchedulerFactory.getScheduler();
			sched.start();
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	/**
	 * 关闭所有定时任务
	 */
	public static void shutdownJobs() {
		try {
			Scheduler sched = gSchedulerFactory.getScheduler();
			if(!sched.isShutdown()) {
				sched.shutdown();
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
}

public class AutoDeployCouponJob extends EJBInvokerJob implements Job {

	private InitialContext ctx;
	@EJB
	private ChmgmTicketCouponInfBO chmgmTicketCouponInfBO;
	@EJB
	private ScheduleTaskBO scheduleTaskBO;

	private static Logger logger = LoggerFactory.getLogger(AutoDeployCouponJob.class);
	@EJB
	private BusinessContentService businessContentService;
	
	private void getContext() {
		try {
			if (ctx == null) {
				ctx = new InitialContext();
			}
			businessContentService = (BusinessContentService) ctx.lookup("BusinessConentServiceImpl/local");
			if (scheduleTaskBO == null) {
				scheduleTaskBO = (ScheduleTaskBO) ctx.lookup("ScheduleTaskBOImpl/local");
			}
			if (chmgmTicketCouponInfBO == null) {
				chmgmTicketCouponInfBO = (ChmgmTicketCouponInfBO) ctx.lookup("ChmgmTicketCouponInfBOImpl/local");
			}
		} catch (NamingException e) {
			e.printStackTrace();
		}
	}

	
	private void deploysTicketCoupon() {
		String today = DateUtil.formatDate(new Date(), "yyyyMMdd");
		List<TblChmgmScheduleTask> list = scheduleTaskBO.queryEffectiveTblChmgmScheduleTasks();
		if (null == list || list.isEmpty()) {
			logger.info("There is no auto deploy coupon schedule task");
			return;
		}
		for (TblChmgmScheduleTask task : list) {
			String publishDate = task.getPublishDate();
			if (today.equalsIgnoreCase(StringUtils.trim(publishDate))) {
				ChmgmTicketCouponInf coupon = chmgmTicketCouponInfBO.findChmgmTicketCouponInfById(task.getBillId());
				if (null != coupon && SystemConstant.BILL_ST_SENDED_UNDEPLOYED.equals(StringUtils.trim(coupon.getBillSt()))) {
					coupon.setBillSt(SystemConstant.BILL_ST_DEPLOYED);
					chmgmTicketCouponInfBO.updateChmgmTicketCouponInf(coupon);
				}
			}
		}
	}
	@Override
	public void execute(JobExecutionContext context) {
		logger.info("---------------- quartz job start----------------");
		getContext();
		deploysTicketCoupon();
		logger.info("---------------- quartz  job  end----------------");
	}
}

遇到的问题是AutoDeployCouponJob 中注入EJB失败,无论使用@annotation还是用JNDI的ookup函数,均无法注入,且系统要求连接数据库使用密文,使用JDBC连接数据库行不通。
提出解决方案两个:
1.EJB3.0的定时任务,优点是直接使用项目的框架,无需额外JAR包支持。缺点是使用麻烦,且定时任务怎么调用不清楚(个人技术水平原因)
2.考虑到在servlet中可以通过@annotation注入EJB,想到了给自身发送request请求。优点是无需额外JAR包支持,缺点是旁门左道。
按照方案二进行。
写了一个GetScheduleRequest 接收处理request请求

public class GetScheduleRequest extends HttpServlet {

	private static final long serialVersionUID = 5369966647967326365L;

	private InitialContext ctx;

	@EJB
	private ChmgmTicketCouponInfBO chmgmTicketCouponInfBO;
	@EJB
	private ScheduleTaskBO scheduleTaskBO;

	private static Logger logger = LoggerFactory.getLogger(AutoDeployCouponJob.class);

	public void init() {
		try {
			ctx = new InitialContext();
			logger.info("Deploy Servlet init success");
		} catch (NamingException e) {
			e.printStackTrace();
			logger.info("Deploy Servlet init faild");
		}
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		String resultStr = "";
		try {
			deploysTicketCoupon();
		} catch (Exception e) {
			e.printStackTrace();
			resultStr = "{\"code\":\"96\",\"msg\":\"" + e + "\"}";
		}
		response.setHeader("ContentType", "text/json");
		response.setCharacterEncoding("utf-8");
		response.getWriter().write(resultStr);
	}
	
	private void deploysTicketCoupon() throws NamingException{
		String today = DateUtil.formatDate(new Date(), "yyyyMMdd");
		List<TblChmgmScheduleTask> list = getScheduleTaskBO().queryEffectiveTblChmgmScheduleTasks();
		if (null == list || list.isEmpty()) {
			logger.info("There is no auto deploy coupon schedule task");
			return;
		}
		for (TblChmgmScheduleTask task : list) {
			String publishDate = task.getPublishDate();
			if (today.equalsIgnoreCase(StringUtils.trim(publishDate))) {
				ChmgmTicketCouponInf coupon = getChmgmTicketCouponInfBO().findChmgmTicketCouponInfById(task.getBillId());
				if (null != coupon && SystemConstant.BILL_ST_SENDED_UNDEPLOYED.equals(StringUtils.trim(coupon.getBillSt()))) {
					try{
						coupon.setBillSt(SystemConstant.BILL_ST_DEPLOYED);
						task.setTaskSt("2");// 2- 执行成功
						getChmgmTicketCouponInfBO().updateChmgmTicketCouponInf(coupon);
					}catch(Exception e){
//						coupon.setBillSt(SystemConstant.BILL_ST_);
						task.setTaskSt("3");// 3- 执行失败
					}finally{
						getScheduleTaskBO().saveOrUpdateTblChmgmScheduleTask(task);
					}
				}
			}
		}
	}
	public ChmgmTicketCouponInfBO getChmgmTicketCouponInfBO() throws NamingException {
		if (chmgmTicketCouponInfBO == null) {
			synchronized (chmgmTicketCouponInfBO) {
				if (chmgmTicketCouponInfBO == null) {
					try {
						chmgmTicketCouponInfBO = (ChmgmTicketCouponInfBO) ctx.lookup("ChmgmTicketCouponInfBOImpl/local");
					} catch (NamingException e) {
						throw e;
					}
				}
			}
		}
		return chmgmTicketCouponInfBO;
	}

	public ScheduleTaskBO getScheduleTaskBO() throws NamingException {
		if (scheduleTaskBO == null) {
			synchronized (scheduleTaskBO) {
				if (scheduleTaskBO == null) {
					try {
						scheduleTaskBO = (ScheduleTaskBO) ctx.lookup("ScheduleTaskBOImpl/local");
					} catch (NamingException e) {
						throw e;
					}
				}
			}
		}
		return scheduleTaskBO;
	}
}
修改JOB类,按照conExpression发送request的请求

public class AutoDeployCouponJob   implements Job {

	static String sessionId = "";
	private static Logger logger = LoggerFactory.getLogger(AutoDeployCouponJob.class);

	/**
	 * 将 内容管理平台票券信息表 tbl_chmgm_ticket_coupon_inf中的bill_St由5更新为2 ; 0- 新建; 1- 待发布
	 * 2- 已发布; 3- 过期 4- 删除 5- 已推送待发布
	 */
	private void sentRequest() throws Exception {
		URL url = new URL("http://localhost:8080/cms-web/getScheduleRequest");
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		connection.setDoOutput(true);
		// Read from the connection. Default is true.
		connection.setDoInput(true);
		// Set the post method. Default is GET
		connection.setRequestMethod("POST");
		// Post cannot use caches
		// Post 请求不能使用缓存
		connection.setUseCaches(false);
		// This method takes effects to
		// every instances of this class.
		// URLConnection.setFollowRedirects是static函数,作用于所有的URLConnection对象。
		// connection.setFollowRedirects(true);
		// This methods only
		// takes effacts to this
		// instance.
		// URLConnection.setInstanceFollowRedirects是成员函数,仅作用于当前函数
		connection.setInstanceFollowRedirects(false);
		// Set the content type to urlencoded,
		// because we will write
		// some URL-encoded content to the
		// connection. Settings above must be set before connect!
		// 配置本次连接的Content-type,配置为application/x-www-form-urlencoded的
		// 意思是正文是urlencoded编码过的form参数,下面我们可以看到我们对正文内容使用URLEncoder.encode
		// 进行编码
		connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
		// 连接,从postUrl.openConnection()至此的配置必须要在connect之前完成,
		// 要注意的是connection.getOutputStream会隐含的进行connect。
		connection.connect();
		Long sendTime = System.currentTimeMillis();
		DataOutputStream out = new DataOutputStream(connection.getOutputStream());
		// 要传的参数
		String content = URLEncoder.encode("SysIdStr", "UTF-8") + "=" + URLEncoder.encode("9C88A47BD4F3B8897447B9956F03A705", "UTF-8");
		content += "&" + URLEncoder.encode("anHaoUP", "UTF-8") + "=" + URLEncoder.encode("tianwanggaidihu", "UTF-8");
		content += "&" + URLEncoder.encode("sendTime", "UTF-8") + "=" + URLEncoder.encode(sendTime.toString(), "UTF-8");
		content = content + "&" + URLEncoder.encode("anhaoDown", "UTF-8") + "=" + URLEncoder.encode("baotazhenheyao", "UTF-8");
		// DataOutputStream.writeBytes将字符串中的16位的unicode字符以8位的字符形式写道流里面
		out.writeBytes(content);
		out.flush();
		out.close(); // flush and close
		// Get Session ID
		String key = "";
		if (connection != null) {
			for (int i = 1; (key = connection.getHeaderFieldKey(i)) != null; i++) {
				if (key.equalsIgnoreCase("set-cookie")) {
					sessionId = connection.getHeaderField(key);
					sessionId = sessionId.substring(0, sessionId.indexOf(";"));
				}
			}
		}
		connection.disconnect();
	}
	@Override
	public void execute(JobExecutionContext context) {
		logger.info("---------------- quartz job start----------------");
		try {
			sentRequest();
		} catch (Exception e) {
			logger.error(e.getLocalizedMessage());
		}
		logger.info("---------------- quartz  job  end----------------");
	}
}

在web.xml配置
 
在web.xml配置
  <servlet>
	    <servlet-name>getScheduleRequest</servlet-name>
	    <servlet-class>com.cup.cms.web.framework.quartz.GetScheduleRequest</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>getScheduleRequest</servlet-name>
        <url-pattern>/getScheduleRequest</url-pattern>
    </servlet-mapping>


记得把/getScheduleRequest这个servlet加到例外,否则会被一般工程的filter过滤掉,楼主在这个地方被坑了。

然后成功了,每间隔5分钟(取决于你的配置"0 0/5  * * * ?")会发送一次request请求,然后读写数据库。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值