本来在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请求,然后读写数据库。