最近做了一个java的项目,部门领导给了一套代码让我尽快掌握,说心里话本人真心不喜欢java的这种项目方式,各种配置各种xml文件简直头都大了,下面就将我遇到的其中一个我认为是坑的地方整理出来,希望能帮助到后面像我一样的兄弟

功能需求说明:

使用Jsoup编写了一套爬虫程序,用来自动录入网站的数据,之前测试都是写在页面中,手动的访问页面触发爬虫(后续一些问题就是因为这样产生的),还有就是项目需要实现自动触发也就是定时器

开发过程:

既然确定是定时器,操刀子就上直接百度java定时器,发现很多quartz、spring、spring-task、Timer ,发现Timer 这东西应该是最简单粗暴的,于是在网上找到下面代码

package tasklListener;

import java.util.TimerTask;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener; import paypay.web.service.timers.ChannelDataSync; /**
* 上下文监听器,需要在web.xml中进行配置,请参见<listener></listener>结点
*
* @author Administrator
*
*/
public class MyContextListener implements ServletContextListener {
private java.util.Timer timer = null;
private ServletContext context = null; public void contextInitialized(ServletContextEvent event) {
this.context = event.getServletContext();
timer = new java.util.Timer(true);
event.getServletContext().log("定时器已启动");
// 设定MyTask中任务每5秒执行一次,0表示马上执行,可以改为2000,则表示2秒以后开始执行
// 以后都按后面指定的每5秒执行一次
timer.schedule(new MyTask(this.context), 60000, 60 * 60 * 2000);
event.getServletContext().log("已经添加任务调度表");
} public void contextDestroyed(ServletContextEvent event) {
timer.cancel();
this.context.log("定时器销毁");
this.context = null;
} private static class MyTask extends TimerTask {
private static boolean isRunning = false;
private ServletContext context = null; public MyTask(ServletContext context) {
this.context = context;
} // 下面的方法会按之前设定的每5秒执行一次,所以,此处不需要循环
public void run() {
if (!isRunning) {
isRunning = true;
context.log("开始执行指定任务"); // TODO 添加自定义的详细任务,以下只是示例
// 这里完成从数据库取数据,然后存放到MySQL数据库中
ChannelDataSync Dateuser=new ChannelDataSync();
java.text.DateFormat df = new java.text.SimpleDateFormat("yyyyMMdd") ;
java.util.Date date = new java.util.Date() ;
String datestr = df.format(new java.util.Date());
Dateuser.selectTSuserdata(datestr); isRunning = false;
context.log("指定任务执行结束");
} else {
context.log("上一次任务执行还未结束");
}
}
}
}

  

建好了类,不对啊怎么触发啊仔细看了一下注释

/**
* 上下文监听器,需要在web.xml中进行配置,请参见<listener></listener>结点
*
* @author Administrator
*
*/
于是到web.xml中找到
	<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class> </listener>

那我就直接复制listener-class节点,然后写入自己的包名+类名

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
<listener-class>
com.shopping.zy.MyContextListener
</listener-class>
</listener>

编译后报错(大神别鄙视我,我是真的java新手,对于配置什么xm文件完全不会啊 )

看了一下报错信息:cvc-complex-type.2.4.d: Invalid content was found starting with element 'listener-class'. No child element is expected at this point.

本人的英文很烂,但也大概看出来说是子元素有问题,既然是子元素不对,那就重新写一个对象不就行了 ,于是配置文件改成:

	<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class> </listener>
<listener>
<listener-class>
com.shopping.zy.MyContextListener
</listener-class> </listener>

测试通过!

再接下来就是在MyContextListener类中做操作了 首先是在定时器的初始化方法contextInitialized中:

         timer = new java.util.Timer(true);
event.getServletContext().log("定时器已启动");
//1000*60*60 1秒 *60=1分钟 *2 等于开启后60分钟执行采集任务
//(1000*60*60)*12 (1000*60*60)=1个小时 *12表示没12小时执行一次
int tempint=(1000*60*60)*(Integer.parseInt(sysconfig.getAotoupdate_step()));
timer.schedule(new MyTask(this.context), 1000*60*60,(1000*60*60)*(Integer.parseInt(sysconfig.getAotoupdate_step())));

具体的可以参看代码,schedule函数的参数是分别是,要调用的函数,延迟执行时间,执行间隔时间 我提供的代码中最后的的执行间隔时间是动态在数据库中取出的所以是动态的,你也可以直接写成固定的

到这了你们肯定觉得没什么坑啊,那么我就先来介绍一下第一个坑:

首先在MyContextListener是不可以直接使用srping的对象的,即使你声明了对应的对象,但由于MyContextListener的启动线程和spring不一致(我自己理解的,如果谁知道可以给我解释一下),在MyContextListener类中使用spring对象是不会有实例化相关的注入对象的,这就坑爹了,总不能自己把所有的数据库操作类重新做一遍吧,于是乎又是神器出山,继续百度,找了半天发现一个帖子中的解决办法:

		 ISysConfigService sysConfigService;
WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext());
sysConfigService = (ISysConfigService) context.getBean("sysConfigService");
SysConfig sysconfig= sysConfigService.getSysConfig();

这里里面有一点是需要注意的:context.getBean("sysConfigService")中的sysConfigService为实体类是我项目中的操作类,但是通过context.getBean()方法返回的对象类型必须是其对应的ISysConfigService接口,而不是其对象类型,

虽然不知道是为什么但我觉得这肯定跟spring的设计模式有关系,这是不是就是工厂类的设计模式啊,在此处坑了我很久也是今天我想写这篇博文的一个诱因吧。这样得到的对象是包括其本身的注入对象的。

接下来就是要实现调用我写好的爬虫函数了 ,这简单啊 ,直接实例化类对象 然后调用方法就行了 ,由于类对象中没有注入对象不需要使用上面的方法,说干就干

ManageHT mht=new ManageHT();

mht.zy_sr_cj(context);
mht.cj_start(context);
mht.zy_collect_news();

 三个方法分别是我对应的三个采集的函数,之前接收的是HttpServletRequest ,但是在MyContextListener中我不知道如何获取,于是我就讲context传入了,如果你知道怎么获取可以给我留言,这不是重点因为后续我使用了其他的办法,

使用上面的方式访问对应的函数会遇到和之前一样的问题,对应的注入对象无法加载,弄了半天最后决定坚持我的简单粗暴的原则,既然直接网页访问可以, MyContextListener不可以,那我就模拟一个网页请求不就行了 还研究什么注入不注入对象的

说干就干:

	   public static String doGet(String url, String queryString, String charset, boolean pretty) {
StringBuffer response = new StringBuffer();
HttpClient client = new HttpClient();
HttpMethod method = new GetMethod(url);
try {
if (StringUtils.isNotBlank(queryString))
//对get请求参数做了http请求默认编码,好像没有任何问题,汉字编码后,就成为%式样的字符串
method.setQueryString(URIUtil.encodeQuery(queryString));
client.executeMethod(method);
if (method.getStatusCode() == HttpStatus.SC_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream(), charset));
String line;
while ((line = reader.readLine()) != null) {
if (pretty)
response.append(line).append(System.getProperty("line.separator"));
else
response.append(line);
}
reader.close();
}
} catch (URIException e) { } catch (IOException e) { } finally {
method.releaseConnection();
}
return response.toString();
}

模拟get请求的操作,对于我的需求来说get/post没什么区别,直接百度一段代码,

最后的调用部分代码变成:

					 String sr = doGet("http://localhost:8080/shopping/admin/testsr.htm", null, "UTF-8", true);
Thread thread = Thread.currentThread();
thread.sleep(1000*60*10);//暂停10分钟后程序继续执行
String mr = doGet("http://localhost:8080/shopping/admin/zy_collect_mr.htm", null, "UTF-8", true);
Thread threadsecond = Thread.currentThread();
threadsecond.sleep(1000*60*10);//暂停10分钟后程序继续执行
String news = doGet("http://localhost:8080/shopping/admin/zy_collect_news.htm", null, "UTF-8", true);

运行项目:执行定时器-执行任务-调用我的爬虫页面,看着数据一条一条进入到数据库中,今天的努力没白费,作为一个新手java程序员我想两说,虽然我对java了解不深,但是java的一些机制确实导致了项目开发进度的缓慢(就是大牛你也得承认,java开发效率就是比.net、python、php)等慢多了 ,这只是我接触java项目以后遇到的比较简单的,之前焦头烂额的也没记录下来,希望以后能把我遇到的问题总结出来,如果再有.net转java的兄弟,希望能让你少走一些弯路。

spring项目中如何添加定时器以及在定时器中自动生成sprng注入对象的更多相关文章

  1. .net core 中简单封装Dapper.Extensions 并使用sqlsuger自动生成实体类

    引言 由公司需要使用dapper  同时支持多数据库 又需要支持实体类 又需要支持sql 还需要支持事务 所以采用了 dapper + dapperExtensions  并配套 生成实体类小工具的方 ...

  2. Spring进阶之路(10)-Advice简单介绍以及通过cglib生成AOP代理对象

    Advice简单介绍 1. Before:在目标方法运行之前运行织入.假设Before的处理中没有进行特殊的处理.那么目标方法终于会运行,可是假设想要阻止目标方法运行时.能够通过抛出一个异常来实现.B ...

  3. Mybatis自动生成的BO对象继承公共父类(BO中过滤掉公共属性)

    使用mybatis的代码生成工具:mybatis-generator,如果自动生成的BO都有公共的属性,则可以指定这些BO继承父类(父类中定义公共属性) 1.定义父类 注意:属性public,不要使用 ...

  4. 利用Django中的url方法实现地址动态拼接自动生成超链接地址

    目标 建立一个图书列表页面,显示图书名列表,并实现点击书名跳转到图书详细页面,显示图书详细信息. URL方法简介 功能:返回一个绝对路径的引用(不包含域名的URL):该引用匹配一个给定的视图函数和 一 ...

  5. Spring JPA 使用@CreatedDate、@CreatedBy、@LastModifiedDate、@LastModifiedBy 自动生成时间和修改者

    JPA Audit 在spring jpa中,支持在字段或者方法上进行注解@CreatedDate.@CreatedBy.@LastModifiedDate.@LastModifiedBy,从字面意思 ...

  6. pycharm中使用配置好的virtualenv环境,自动生成和安装requirements.txt依赖

    1.手动建立: 第一步 建立虚拟环境 Windows cmd: pip install virtualenv 创建虚拟环境目录 env 激活虚拟环境 C:\Python27\Scripts\env\S ...

  7. 给.Net Core添加Swagger实现接口文档自动生成

    1.添加Nuget相关引用 Swashbuckle.AspNetCore

  8. mybatis 添加后获得该新增数据自动生成的 id

    // useGeneratedKeys默认值为false,keyProperty的值对应的是User类中的主键字段名 // mybatis 写法如下 <insert id="inser ...

  9. 淘淘商城项目_同步索引库问题分析 + ActiveMQ介绍/安装/使用 + ActiveMQ整合spring + 使用ActiveMQ实现添加商品后同步索引库_匠心笔记

    文章目录 1.同步索引库问题分析 2.ActiveM的介绍 2.1.什么是ActiveMQ 2.2.ActiveMQ的消息形式 3.ActiveMQ的安装 3.1.安装环境 3.2.安装步骤 4.Ac ...

随机推荐

  1. Swift 实现Bitmask Option(Enum)

    在Swift中实现ObjC中的NS_OPTION不是通过enum,而是通过conform RawOptionSetType protocol的struct来实现的. 代码如下: struct Test ...

  2. linux集群管理<转>

    云在根本上是由硬件和软件组成的,这些组件需要经常细心地维护.出现故障的硬件需要修理或更换:软件需要应用补丁.更新和升级:必须根据需求和潜在的安全威胁提前配置系统.应用程序开发人员可能觉得计算云很方便. ...

  3. [转]iOS应用性能调优的25个建议和技巧

    写在前面 本文来自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iOS 程序员.这是他的个人网站:http://www.marcelofabri.com/ ...

  4. Codeforces Round #309 (Div. 1) C. Love Triangles dfs

    C. Love Triangles Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/553/pro ...

  5. [AngularJS] Hijacking Existing HTML Attributes with Angular Directives

    Angular overrides quite a few existing HTML elements and attributes. This can be a useful technique ...

  6. jQuery 属性操作 - addClass() 方法

    使用 addClass() 和 removeClass() 来移除 class,并添加新的 class. <html> <head> <script type=" ...

  7. 查询记录时rs.previous()的使用

    查询记录时rs.previous()的使用 假如查询一个数据表,假设没有记录就显示提示信息,有就所有显示出来查询结果.这时假设是有查询结果的话就须要进行两次查询,第一次查完记录指针指向最后一条记录,開 ...

  8. JavaScript目录

    1. 如何快速检查js语法学习Javascript 2. 如何快速掌握CSS(各种CSS工具)

  9. 实例源码--Android图片滚动切换效果

    下载源码 技术要点:  1.图片滚动切换技术 2.详细的源码注释 ...... 详细介绍: 1.图片滚动切换技术 本套源码实现了类似于网站图片滚动推广效果,效果不错,很不错的参考源码 2.源码目录 运 ...

  10. flume1.5.2安装与简介

    关于flume的简介看参考:http://www.aboutyun.com/thread-7415-1-1.html 其实一张图就简单明了了 简单安装: 1.下载解压 ... 2.配置JDK,flum ...