2 yanxin9210 yanxin9210 于 2016.03.29 17:22 提问

在java timer定时器中调用dao层会报错

现在在做一个web项目,使用spring+springMVC+hibernate框架,

问题描述:
项目中有一个扫描的功能,分即时任务、定时任务、周期任务三种,即时任务已经实现了,现在使用java.util.Timer、java.util.TimerTask类做定时任务,重写TimerTask的run方法,在run方法中调用之前已经没有问题的即时任务扫描方法。每次运行定时任务时,会卡在dao层方法的调用上,因为在即时任务的扫描方法中调用了dao层的数据操作方法,报错“No Session found for current thread”。

即时任务的执行流程:前台提交即时任务扫描请求->控制器调用service层的立即扫描方法startImmediateTask();
定时任务的执行流程:前台提交定时任务扫描请求->控制器调用service层的定时扫描方法startTimerTask()->调用立即扫描方法startImmediateTask()。

下面附上代码和配置文件,请各位大牛帮忙解决啊!

service层代码

 /**
     * 开始定时扫描任务
     * @param blTask
     */
public void startTimerTask(final BLTask blTask) {
        Date startDate = blTask.getStartTime();
        TimerTask task = new TimerTask() {

            @Override
            public void run() {
            // 调用扫描方法
                startImmediateTask(blTask);
            }
        };
        Timer timer = new Timer();
        timer.schedule(task, startDate);        
    }


/**
     * 开始即时扫描任务
     * @param blTask
     */
 public void startImmediateTask(BLTask blTask) {

        BLScanParam blScanParam = new BLScanParam();
        BLPolicyGroup blPolicyGroup = null; // 策略组
        List<BLCheckItem> blCheckItems = null; // 检查项
        Map<Long, BLCheckScript> blCheckScriptMap = new HashMap<Long, BLCheckScript>(); // 检查脚本

        Long pgId = null; // 策略组ID
        String alias = null; // 策略别名、检查项别名
        Long osType = blTask.getOsType(); // 操作系统类型
        List<Long> csIds = new ArrayList<Long>(); // 检查脚本ID数组

        blScanParam.setBlTask(blTask);

        pgId = blTask.getPgId();
        // 通过策略组ID查找策略组
        blPolicyGroup = blPolicyGroupDao.get(pgId);

        if (blPolicyGroup == null) {
            return;
        }
        blScanParam.setBlPolicyGroup(blPolicyGroup);
        alias = blPolicyGroup.getAlias();

        // 通过别名、操作系统类别查找所有匹配的检查项
        blCheckItems = blCheckItemDao.queryByProerties(new String[]{"alias", "osType"}, new Object[]{alias, osType});

        if (blCheckItems == null || blCheckItems.size() <= 0) {
            return;
        }
        blScanParam.setBlCheckItems(blCheckItems);

        for (BLCheckItem blCheckItem : blCheckItems) {
            csIds.add(blCheckItem.getCsId());
        }
        int size = csIds.size();

        // 获取当前策略组下的所有检查项的检测脚本
        List<BLCheckScript> blCheckScripts = blCheckScriptDao.queryByProerties("csId", (Long[])csIds.toArray(new Long[size]));

        for (BLCheckScript blCheckScript : blCheckScripts) {
            // 获取当前策略组下的所有检测脚本,并放入map中
            blCheckScriptMap.put(blCheckScript.getCsId(), blCheckScript);
        }

        blScanParam.setBlCheckScriptMap(blCheckScriptMap);

        // 分割ip为数组,传入TaskDispatch
        String[] ips = getIps(blTask.getIpArea());
        TaskDispatch taskDispatch = new TaskDispatch(ips, blScanParam);
        taskDispatch.StartTask();

        // 将当前TaskDispatch对象的引用放入taskDispatchMap中,供停止任务时使用
        taskDispatchMap.put(blTask.getTkId(), taskDispatch);
    }

BaseDao的部分代码

public class BaseDao<E> implements Dao<E> {
 public SessionFactory getSessionFactory() {
        return this.sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public Session getSession() {
        return this.sessionFactory.getCurrentSession();
    }

    @Resource(name = "sessionFactory")
    public void setSF(SessionFactory sessionFactory) {
        setSessionFactory(sessionFactory);
    }
}

applicationContext.xml

 <?xml version="1.0" encoding="UTF-8"?>
    <context:annotation-config />
    <context:component-scan base-package="com.djbh" />

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">

        <property name="driverClass" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUrl" value="jdbc:mysql://192.168.1.247:3306/djbh_db?useUnicode=true&amp;characterEncoding=utf-8" />
        <property name="user" value="root" />
        <property name="password" value="mysql" />


        <!--
        <property name="driverClass" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
        <property name="jdbcUrl" value="jdbc:sqlserver://localhost:1433;DatabaseName=DJBH_DB" />
        <property name="user" value="sa" />
        <property name="password" value="123456" />
        -->
        <property name="acquireIncrement" value="3" />
        <property name="idleConnectionTestPeriod" value="120" />
        <property name="initialPoolSize" value="3" />
        <property name="minPoolSize" value="3" />
        <property name="maxPoolSize" value="15" />
        <property name="numHelperThreads" value="3" />
        <property name="preferredTestQuery" value="select 1" />
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                <!-- <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop> -->
                <!-- <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop> -->
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.use_outer_join">true</prop>
                <prop key="hibernate.jdbc.fetch_size">30</prop>
                <prop key="hibernate.jdbc.batch_size">30</prop>
                <prop key="hibernate.jdbc.batch_versioned_data">true</prop>
                <prop key="hibernate.cache.use_second_level_cache">true</prop>
                <prop key="hibernate.cache.use_query_cache">true</prop>
                <prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop>
                <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
                <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="javax.persistence.validation.mode">none</prop>
            </props>
        </property>
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan">
            <list>
                <value>com.djbh.model</value>
            </list>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />

    <!-- 启动对@AspectJ注解的支持 -->
    <aop:aspectj-autoproxy/>

</beans>

springmvc-servlet.xml

 <?xml version="1.0" encoding="UTF-8"?>
    <mvc:annotation-driven/>

    <mvc:resources location="/static/" mapping="/static/**"/>
    <mvc:resources location="/attachment/report_html/" mapping="/attachment/report_html/**"/> 

    <context:component-scan base-package="com.djbh.controller" />

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
        <property name="viewClass"><value>org.springframework.web.servlet.view.JstlView</value></property> 
        <property name="prefix"><value>/WEB-INF/page/</value></property> 
        <property name="suffix"><value>.jsp</value></property>
    </bean>

    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="messages" />
        <property name="useCodeAsDefaultMessage" value="true" />
    </bean>

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--<property name="maxUploadSize" value="10485760"></property> -->
    </bean> 

    <aop:aspectj-autoproxy proxy-target-class="true" />
</beans>


web.xml

 <?xml version="1.0" encoding="UTF-8"?>
    <display-name>djbh</display-name>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath*:applicationContext*.xml
        </param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>core.web.SystemInitListener</listener-class>
    </listener>
    <filter>
        <filter-name>loginFilter</filter-name>
        <filter-class>core.web.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>loginFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>openSessionInViewFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
        <init-param>
            <param-name>singleSession</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>openSessionInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>characterEncoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
    </welcome-file-list>
</web-app>

1个回答

w172087242
w172087242   Ds   Rxr 2016.03.29 17:43

startTimerTask是什么时候调用的,贴出来的信息太少了

w172087242
w172087242 回复yanxin9210: 保持所有操作都是spring管理的才能保证ioc的完全注入,所以需要所有实现流程才知道,你也可以看看梳理你的流程。
一年多之前 回复
yanxin9210
yanxin9210 前台发起定时任务扫描请求时,处理扫描请求的控制器就会调用startTimerTask
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!