又是一个愚蠢的错误,皆因.xml而起

   论java中的.xml到底有多坑?!

感觉自己都快哭了,再一次被.xml给坑了一下,这次坑的太狠了,一下子导致自己浪费了昨天一下午,一晚上,今天一上午和半个下午呀,中间的过程真的是乏善可陈呀,各种转折,各种离奇的错误,自己都崩溃了好多次,让我一一来诉说吧。

1、在springmvc分层结构中(分为mybatis层、service层、controller层)自己定义了一个定时器,定时器是定义在service的配置文件中的,文件如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3  xmlns:aop="http://www.springframework.org/schema/aop"
 4  xmlns:mvc="http://www.springframework.org/schema/mvc"
 5  xmlns:context="http://www.springframework.org/schema/context"
 6  xmlns:p="http://www.springframework.org/schema/p"
 7  xmlns:tx="http://www.springframework.org/schema/tx"
 8  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 9
10  xmlns:task="http://www.springframework.org/schema/task"
11
12  xsi:schemaLocation="
13          http://www.springframework.org/schema/mvc
14          http://www.springframework.org/schema/mvc/spring-mvc.xsd
15         http://www.springframework.org/schema/beans
16         http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
17         http://www.springframework.org/schema/context
18         http://www.springframework.org/schema/context/spring-context-3.2.xsd
19         http://www.springframework.org/schema/aop
20         http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
21         http://www.springframework.org/schema/tx
22         http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
23
24         http://www.springframework.org/schema/task
25                         http://www.springframework.org/schema/task/spring-task-3.2.xsd"        >
26
27
28         <!-- 定义service -->
29         <!-- 扫描controller交给前段控制器,service包中的注解交给此配置扫描 -->
30     <context:component-scan base-package="service" >   </context:component-scan>
31     <!-- 第二个扫描项bean包 -->
32     <context:component-scan base-package="bean" > </context:component-scan>
33
34
35        <task:annotation-driven/> 
36
37 </beans>        

代码中加粗的部分是定时器的关键,注意这里一定要配置在service层,如果配置到了spring-mvc.xml层,就没有反应,这也是我以前犯的一个愚蠢的错误,究其原因,这和springmvc运行的机理有关,如果没有得到合理的初始化,没有被扫描到都是执行不了的。

之后就可以在service层写定时器的代码了,其实也简单,但是写完之后一定要注意配置扫描,这个地方,因为整个service层都被扫描了,所以无论放在哪里都可以,也不用在.xml中配置了。

定时器的代码如下:

@Component
public class StatisticsTimer {
    private static Logger logger = Logger.getLogger(StatisticsTimer.class);

     //定时器测试
    @Scheduled(cron="0/20 * *  * * ? ")
    public void statisticsTimerCycle(){

         System.out.println("============begining===============");
        //一些代码
        System.out.println("============end===============");

    }
}

这里要注意加入的部分,之后运行程序,就可以看到每隔一段时间就打印出来一些东西了。

可是在大型项目中,定时器都是用来处理SQL语句的,也就是要进行数据库操作,这个时候,因为我是用的mybatis这个框架,其中配置之后就可以自动扫描来生成代码了,根本就不用我来配置,我就理所当然的使用依赖注入想要的语句,之后来查询数据库,可是一直报错,意思是说mybatis不能找到我要调用的查找方法,在这里我要说明一点,那些mapper以及相应的.xml都是我自己写的,因为自动生成的可能满足不了的我的要求,也正是因为这个原因我就悲剧了,还记得当时写这个东西是在我电脑出了点问题的时候,我没有在工程里面写,而是在一个文本编辑器中写的,这就造成了一些东西是我手打出来的,而不是复制的,这样就很容易错过一个或者两个字母,而这次我竟然真的是犯了这个错,就是因为我在.xml中少写了一个字母‘s’,而我当时不知道呀,再加上对自己的编码能力太自信了吧,想哭。。。

 1 17-12-06-14-55-40-001-ERROR-[pool-1-thread-1]-Unexpected error occurred in scheduled task.
 2 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): mapper.part.OrderStatisticsPartMapper.selectOrdersInfoByToday
 3     at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:189)
 4     at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:43)
 5     at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:58)
 6     at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:51)
 7     at com.sun.proxy.$Proxy44.selectOrdersInfoByToday(Unknown Source)
 8     at service.statistics.OrderStatisticsOperator.selectOrdersInfoByToday(OrderStatisticsOperator.java:25)
 9     at service.timer.StatisticsTimer.statisticsTimerCycle(StatisticsTimer.java:55)
10     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
11     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
12     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
13     at java.lang.reflect.Method.invoke(Method.java:497)
14     at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:64)
15     at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:53)
16     at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
17     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
18     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
19     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
20     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
21     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
22     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
23     at java.lang.Thread.run(Thread.java:745)
1     @Autowired
2     private OrderStatisticsOperator orderStatisticsOperator;

首先我给大家看一下我的这些相关文件吧:

1.罪恶之源:OrderStatisticsPartMapper.xml,看到了吗,这就是我标出的那个我错的地方,其实是Orders而不是Order!!!!!!

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 3 <mapper namespace="mapper.part.OrderStatisticsPartMapper">
 4
 5   <resultMap id="order_statistics_part" type="pojo.part.OrderStatisticsPart">
 6     <result column="order_id" jdbcType="VARCHAR" property="orderId" />
 7     <result column="shop_account_id" jdbcType="INTEGER" property="shopAccountId" />
 8     <result column="wating_start_time" jdbcType="VARCHAR" property="watingStartTime" />
 9     <result column="waiting_end_time" jdbcType="VARCHAR" property="waitingEndTime" />
10     <result column="pay_total_price" jdbcType="DECIMAL" property="payTotalPrice" />
11   </resultMap>
12
13     <select id="selectOrderInfoByToday" resultMap="order_statistics_part">
14         select order_id ,shop_account_id , wating_start_time , waiting_end_time , pay_total_price
15         from orders
16
17     </select>
18
19 </mapper>

2.对应的接口类:OrderStatisticsPartMapper

 1 package service.statistics;
 2 import java.util.List;
 3
 4 import org.springframework.beans.factory.annotation.Autowired;
 5 import org.springframework.stereotype.Service;
 6
 7 import pojo.part.OrderStatisticsPart;
 8 import mapper.part.OrderStatisticsPartMapper;
 9
10 /**
11  * @author zyr
12  * 按日期查询当天商城消费订单信息
13  */
14 public interface OrderStatisticsInterface {
15
16     public List<OrderStatisticsPart> selectOrdersInfoByToday(String today_date);
17 }

     3.OrderStatisticsOperator类,service层,对上面的方法进行封装

 1 package service.statistics;
 2 import java.util.List;
 3
 4 import javax.transaction.Transactional;
 5
 6 import org.springframework.beans.factory.annotation.Autowired;
 7 import org.springframework.stereotype.Service;
 8
 9 import pojo.part.OrderStatisticsPart;
10 import mapper.part.OrderStatisticsPartMapper;
11
12 /**
13  * @author zyr
14  * 按日期查询当天商城消费订单信息
15  */
16 @Service("orderStatisticsOperator")
17 //@Service("orderStatisticsInterface")
18 @Transactional
19 //public class OrderStatisticsOperator implements OrderStatisticsInterface{
20 public class OrderStatisticsOperator{
21     @Autowired
22     private OrderStatisticsPartMapper orderStatisticsPartMapper;
23 //    @Override
24     public List<OrderStatisticsPart> selectOrdersInfoByToday(String today_date) {
25          return orderStatisticsPartMapper.selectOrdersInfoByToday(today_date);
26     }
27 }

4.ApplicationContextUtil类,要注意在以前博客上的代码中是没有@Component的!!!!!!

 1 package service.timer;
 2
 3 import org.apache.log4j.Logger;
 4 import org.springframework.context.ApplicationContext;
 5 import org.springframework.context.ApplicationContextAware;
 6 import org.springframework.stereotype.Component;
 7 import org.springframework.stereotype.Controller;
 8
 9 /**
10  * @author zyr
11  * 由于定时器的执行优先于注入,因此我们不能通过@Resource注入service
12  * 因此需要创建一个类ApplicationContextUtil,用来获取service
13  */
14 @Component
15 public class ApplicationContextUtil implements ApplicationContextAware{
16     private static ApplicationContext applicationContext;
17     private static Logger logger = Logger.getLogger(ApplicationContextUtil.class);
18
19
20     public static ApplicationContext getApplicationContext() {
21         return applicationContext;
22     }
23
24     public  void setApplicationContext(ApplicationContext applicationContext) {
25         logger.debug("------SpringContextUtil setApplicationContext-------");
26         ApplicationContextUtil.applicationContext = applicationContext;
27     }
28     public static Object getBean(String beanName)
29     {
30         return  applicationContext.getBean(beanName);
31     }
32 }

如果我之前看到该多好呀,可惜是一天之后了,下面我来给大家说一下我看到这个错误做了什么事情!!!

首先我在网上搜索了这个问题,还真的让我给找到了一个同样的问题,就是这篇“该死的博客”让我一直苦逼不堪!!!!!!

http://blog.csdn.net/u011277123/article/details/54285896

根据这篇博客上说的,我发现这就是我的翻版呀,哈哈,然后我开开心心的起了个大早就来搞这个东西了,结果这个博客上有一点不清楚的地方,那就是@Service("一些名称"),括号中的东西到底应该是什么,当然可以是任意字符串,那意思呢,因为我当时直接在OrderStatisticsOperator中直接写了@Service("orderStatisticsOperator")这样的东西,并且在定时器中,使用:

1 OrderStatisticsOperator orderStatisticsOperator=(OrderStatisticsOperator)ApplicationContextUtil.getBean("orderStatisticsOperator");

来直接运行,结果就错了,错了,当然了,在以前的博客上是没有@Component的,因此报的错一直是空指针错误,让我们看一下这个语句,一直报错,这浪费我三个多小时,我一直搞不懂这个东西为什么会报错,而且是空指针错误,因为程序一直卡在ApplicationContextUtil.getBean("orderStatisticsOperator");这个语句上面,提示这个语句空指针错误,我在想是不是beanName中传进的参数orderStatisticsOperator的错,可是也没错呀,如果是全称的话也可以的,但是我已经在@Service中表明了这个名字,应该没错的,那是怎么回事呢,想呀想,改不成是applicationContext的错吧,因为applicationContext.getBean(beanName);,如果applicationContext为空,那么将会是null..getBean(beanName);那么肯定会是空指针异常了,这让我绝望,因为我们的这个类是继承自ApplicationContextAware的,这个东西里面我们重载了 getBean(String beanName)方法和setApplicationContext(ApplicationContext applicationContext) 方法,也就是说在程序运行的时候,加载的过程中就会调用setApplicationContext对我们的applicationContext赋值了,这个意思是应用上下文,当然是在这个时候就给我们的了,可是还是出错,到底是怎么回事呢,我把这个文件放到了controller层还是不行,因为我在另一篇博客上看到,这个定时任务是Spring的,而不是Springmvc上面的应该,而前者比后者先初始化,也就是说前者是后者的父亲,Springmvc是Spring的孩子,应该现在父亲那边初始化才能因为继承的关系在Springmvc中有效,可是放到了controller中还是没用呀,真的坑。。。于是我又进行了一些细微的修改还是不行

1     public static Object getBean(String beanName)
2     {
3         return  applicationContext.getBean(beanName);
4     }

就在我快要绝望的时候,突然想起来,我们把这个自己定义的类当做bean,却没有能够让框架扫描到这个东西,因为没有暴露任何东西,所以我在这个类的前面加了个@Component,也就是在这个时候奇迹出现了,程序总算不在报空指针错误了,原来自己之前的所有操作都是因为没有加这个东西,不能让框架扫描到,当然是不能调用里面重载的setApplicationContext方法,从而applicationContext就是空null的,按理说这样总算是解决了问题了,我又运行一下程序,谁知道还是在报以前的错误,mybatis解析不了,我的天呀,当时我的心态真的是爆炸了,想的是原来这个东西,我搞了这么长时间,总算把bean注入到了我需要的地方了,却没有任何效果,就在我痛定思痛的时候,我想到了是不是因为我的那个mapper.xml真的有问题呢,因为以前就有这样的问题,后来我仔细一看还真是有问题,就是少了一个‘s’,我的天,我的世界电闪雷鸣了,赶紧改过来再运行一下,结果正常了,正常了,正常了!!!!!!后来我在想既然用了这个新的类我的程序正常了,并且这个时候我还实现了一个operator的接口,这是我从其他博客中学到的,接口如下:

 1 package service.statistics;
 2 import java.util.List;
 3
 4 import org.springframework.beans.factory.annotation.Autowired;
 5 import org.springframework.stereotype.Service;
 6
 7 import pojo.part.OrderStatisticsPart;
 8 import mapper.part.OrderStatisticsPartMapper;
 9
10 /**
11  * @author zyr
12  * 按日期查询当天商城消费订单信息
13  */
14 public interface OrderStatisticsInterface {
15
16     public List<OrderStatisticsPart> selectOrdersInfoByToday(String today_date);
17 }

调用的方法如下:

1 OrderStatisticsInterface orderStatisticsInterface=(OrderStatisticsInterface)ApplicationContextUtil.getBean("orderStatisticsInterface");

这样是正常的,那么我不用接口呢?也就是:

1  OrderStatisticsOperator orderStatisticsOperator=(OrderStatisticsOperator)ApplicationContextUtil.getBean("orderStatisticsOperator");

我试了一下,把一些相应的地方改了一下,竟然也正常了,我哭。。。。

后来想了一下干脆不用这个类,我试一下怎么样,我当时想的是肯定是不行的,谁知道呀,竟然可以了,可以了。。。

也就是这样做,竟然成功了,和我以前编程的方法一模一样,真的是让人难以接受呀!!!!!!原来自己搞了一天的时间就是因为一个字母,只是一个字符呀,都不是字符串,哇哇~~~

 1 @Component
 2 public class StatisticsTimer {
 3     @Autowired
 4     private OrderStatisticsOperator orderStatisticsOperator;
 5     private static Logger logger = Logger.getLogger(StatisticsTimer.class);
 6     //一次性查询所有的订单相关信息
 7     private List<OrderStatisticsPart> orderStatisticsList = new ArrayList<OrderStatisticsPart>();
 8      //定时器测试
 9     @Scheduled(cron="0/20 * *  * * ? ")
10 //    @Scheduled(cron="0 59 23 ? * *")
11     public void statisticsTimerCycle(){
12         System.out.println("============begining===============");
13         //按时间查询该天商城的所用订单,返回订单的中需要用到的字段,实现统计功能
14        // OrderStatisticsOperator orderStatisticsOperator=(OrderStatisticsOperator)ApplicationContextUtil.getBean("orderStatisticsOperator");
15 //        ApplicationContext appCtx = ApplicationContextUtil.getApplicationContext();
16 //        logger.debug(appCtx);
17 //        if(appCtx==null)
18 //        {
19 //            logger.debug("ApplicationContext  为空");
20 //        }
21             //        OrderStatisticsOperator orderStatisticsOperator=(OrderStatisticsOperator)ApplicationContextUtil.getBean("orderStatisticsOperator");
22 //
23 //        OrderStatisticsInterface orderStatisticsInterface=(OrderStatisticsInterface)ApplicationContextUtil.getBean("orderStatisticsInterface");
24         System.out.println(orderStatisticsOperator);
25         System.out.println("===========暂无问题===============");
26         orderStatisticsList= orderStatisticsOperator.selectOrdersInfoByToday(DateTimeTool.get_now_date());
27         System.out.println("============end===============");
28 //        //当前销售菜品统计
29 //        dishStatisticsTask();
30 //        //当前商家销售情况统计
31 //        shopStatisticsTask();
32 //        //当前商家等位时间统计
33 //        waitingTimeStatisticsTask();
34     }

到了这一步,我可以看到,首先是在网上找的那个程序有问题,没有在类的前面加上@Component,加上了之后使用这个方法也是可以的;

其次,就是无论实现不实现接口和类,其实都是可以的,不一定非要用接口;

最后就是我的程序最本质的错误是在mapper.xml上,这个东西真的坑,以后一定要加倍小心,特别是刚才那种错误,真的是难以发现呀!!!!!!

因此我觉得.xml真的是一个让程序员又爱又恨的东西,爱的原因是这种文件为程序员节约了大量的时间,想要什么功能只要简单的配置就好了,甚至可以灵活地改变自己需要的东西,实现不同的功能,剩下的就交给web容器去解决了,这点来说真的是神器,可是与之相对应的就是对于一些出错信息缺少智能提示的问题,要知道一个好的开发环境是能够让程序员快速而准确地定位自己的错误,并且找到相应的解决办法的,而这个.xml文件对于“”里面的东西是没有解析能力的,只能够处理最基本的语法,比如结构不对称等,这显示是低级的,从可能性的角度来说,.xml在以后还是可能走向越来越智能的道路的,只不过框架这样做的话效率会下降吧,就如我之前说的这个错误,有的时候是在所难免的,人非圣贤,孰能无过,只不过错了却不一定会往这方面想呀,再加上myeclipse报的错误往往有误导的作用,特别是.xml文件出错的情况下,基本上都是没有参考价值的,正如我上一次在.xml中对于一个参数类型的描述,本来是jdbcType=VARCHAR的,而我写成了,jdbcType=String,结果给我报的错误,那是真的让人绝望呀,最后找了好久才找到,大大的浪费了开发的时间,就像这个错误浪费了我一天的时间一样,那个错误也整整浪费了我的大半天,与其他开发工具相比,我还是觉得java需要在这个方面改进一下,让.xml更加的智能起来,这样才能成为大家更喜爱的开发软件。当然了在我的这个错误中,使用网上说的那个方法也是可以的,但是一定要注意一些细节。下面,我对这几种方法进行梳理:

方法一:使用原生的方法,直接依赖注入。

1.1、OrderStatisticsPartMapper.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 3 <mapper namespace="mapper.part.OrderStatisticsPartMapper">
 4
 5   <resultMap id="order_statistics_part" type="pojo.part.OrderStatisticsPart">
 6     <result column="order_id" jdbcType="VARCHAR" property="orderId" />
 7     <result column="shop_account_id" jdbcType="INTEGER" property="shopAccountId" />
 8     <result column="wating_start_time" jdbcType="VARCHAR" property="watingStartTime" />
 9     <result column="waiting_end_time" jdbcType="VARCHAR" property="waitingEndTime" />
10     <result column="pay_total_price" jdbcType="DECIMAL" property="payTotalPrice" />
11   </resultMap>
12
13     <select id="selectOrdersInfoByToday" resultMap="order_statistics_part">
14         select order_id ,shop_account_id , wating_start_time , waiting_end_time , pay_total_price
15         from orders
16
17     </select>
18
19 </mapper>

1.2、OrderStatisticsPartMapper接口

 1 package mapper.part;
 2
 3 import java.util.List;
 4
 5 import org.apache.ibatis.annotations.Param;
 6 import org.mybatis.spring.annotation.MapperScan;
 7
 8 import pojo.part.OrderStatisticsPart;
 9
10 /**
11  * @author zyr
12  * 查询当天该商城产生的所有订单信息
13  * 并返回信息需要的字段
14  */
15 public interface OrderStatisticsPartMapper {
16     List<OrderStatisticsPart> selectOrdersInfoByToday(@Param("today_date")String today_date);
17 }

1.3.OrderStatisticsOperator:service层,其实也可以不用,直接在定时器中调用mapper

 1 package service.statistics;
 2 import java.util.List;
 3
 4 import javax.transaction.Transactional;
 5
 6 import org.springframework.beans.factory.annotation.Autowired;
 7 import org.springframework.stereotype.Service;
 8
 9 import pojo.part.OrderStatisticsPart;
10 import mapper.part.OrderStatisticsPartMapper;
11
12 /**
13  * @author zyr
14  * 按日期查询当天商城消费订单信息
15  */
16 @Service
17
18 public class OrderStatisticsOperator{
19     @Autowired
20     private OrderStatisticsPartMapper orderStatisticsPartMapper;
21
22     public List<OrderStatisticsPart> selectOrdersInfoByToday(String today_date) {
23          return orderStatisticsPartMapper.selectOrdersInfoByToday(today_date);
24     }
25 }

1.4.定时器任务类:StatisticsTimer

 1 package service.timer;
 2 import java.util.ArrayList;
 3 import java.util.List;
 4
 5 import mapper.DishSaleStatisticsMapper;
 6 import mapper.part.OrderStatisticsPartMapper;
 7
 8 import org.apache.log4j.Logger;
 9 import org.springframework.beans.factory.annotation.Autowired;
10 import org.springframework.context.ApplicationContext;
11 import org.springframework.context.annotation.Configuration;
12 import org.springframework.scheduling.annotation.Scheduled;
13 import org.springframework.stereotype.Component;
14 import org.springframework.stereotype.Service;
15
16 import pojo.part.OrderDetailStatisticsPart;
17 import pojo.part.OrderStatisticsPart;
18 import service.statistics.DishSaleStatisticsOperator;
19 import service.statistics.OrderDetailStatisticsOperator;
20 import service.statistics.OrderStatisticsInterface;
21 import service.statistics.OrderStatisticsOperator;
22 import service.statistics.ShopSaleStatisticsOperator;
23 import service.statistics.WaitingTimeStatisticsOperator;
24 import tools.time.DateTimeTool;
25
26 /**
27  * @author zyr
28  * 系统定时器,每一天定时运行一次,进行统计工作
29  */
30 @Component
31 public class StatisticsTimer {
32     @Autowired
33     private OrderStatisticsOperator orderStatisticsOperator;
34     private static Logger logger = Logger.getLogger(StatisticsTimer.class);
35     //一次性查询所有的订单相关信息
36     private List<OrderStatisticsPart> orderStatisticsList = new ArrayList<OrderStatisticsPart>();
37      //定时器测试
38     @Scheduled(cron="0/20 * *  * * ? ")
39     public void statisticsTimerCycle(){
40         System.out.println("============begining===============");
41         //按时间查询该天商城的所用订单,返回订单的中需要用到的字段,实现统计功能
42
43         System.out.println(orderStatisticsOperator);
44         System.out.println("===========暂无问题===============");
45         orderStatisticsList= orderStatisticsOperator.selectOrdersInfoByToday(DateTimeTool.get_now_date());
46         System.out.println("============end===============");
47     }
48 }

就这样一个程序就可以正常工作了,当然定时器要有之前的配置,这里不再赘述。

方法二:使用ApplicationContextUtil,继承ApplicationContextAware,并且不创建新的服务层接口

首先,方法一中的OrderStatisticsPartMapper.xmlOrderStatisticsPartMapper接口都没变。

其次在以前的服务中作如下修改:

 1 package service.statistics;
 2 import java.util.List;
 3
 4 import javax.transaction.Transactional;
 5
 6 import org.springframework.beans.factory.annotation.Autowired;
 7 import org.springframework.stereotype.Service;
 8
 9 import pojo.part.OrderStatisticsPart;
10 import mapper.part.OrderStatisticsPartMapper;
11
12 /**
13  * @author zyr
14  * 按日期查询当天商城消费订单信息
15  */
16 @Service("orderStatisticsOperator")
17 public class OrderStatisticsOperator{
18     @Autowired
19     private OrderStatisticsPartMapper orderStatisticsPartMapper;
20     public List<OrderStatisticsPart> selectOrdersInfoByToday(String today_date) {
21          return orderStatisticsPartMapper.selectOrdersInfoByToday(today_date);
22     }
23 }

并且增加一个新的类:ApplicationContextUtil,注意红色的部分!!!!!!

 1 package service.timer;
 2
 3 import org.apache.log4j.Logger;
 4 import org.springframework.context.ApplicationContext;
 5 import org.springframework.context.ApplicationContextAware;
 6 import org.springframework.stereotype.Component;
 7 import org.springframework.stereotype.Controller;
 8
 9 /**
10  * @author zyr
11  * 由于定时器的执行优先于注入,因此我们不能通过@Resource注入service
12  * 因此需要创建一个类ApplicationContextUtil,用来获取service
13  * 但是经过测试,事实并非如此,与版本有关
14  */
15 @Component
16 public class ApplicationContextUtil implements ApplicationContextAware{
17     private static ApplicationContext applicationContext;
18     private static Logger logger = Logger.getLogger(ApplicationContextUtil.class);
19
20
21     public static ApplicationContext getApplicationContext() {
22         return applicationContext;
23     }
24
25     public  void setApplicationContext(ApplicationContext applicationContext) {
26         logger.debug("------SpringContextUtil setApplicationContext-------");
27         ApplicationContextUtil.applicationContext = applicationContext;
28     }
29     public static Object getBean(String beanName)
30     {
31         return  applicationContext.getBean(beanName);
32     }
33 }

然后在定时器中:其中注释的部分也可以打开,看看对象是否为空,肯定不空!一定要注意@Component!!!!!!

 1 /**
 2  * @author zyr
 3  * 系统定时器,每一天定时运行一次,进行统计工作
 4  */
 5 @Component
 6 public class StatisticsTimer {
 7     private static Logger logger = Logger.getLogger(StatisticsTimer.class);
 8     //一次性查询所有的订单相关信息
 9     private List<OrderStatisticsPart> orderStatisticsList = new ArrayList<OrderStatisticsPart>();
10      //定时器测试
11     @Scheduled(cron="0/20 * *  * * ? ")
12     public void statisticsTimerCycle(){
13         System.out.println("============begining===============");
14         //按时间查询该天商城的所用订单,返回订单的中需要用到的字段,实现统计功能
15         OrderStatisticsOperator orderStatisticsOperator=(OrderStatisticsOperator)ApplicationContextUtil.getBean("orderStatisticsOperator");
16 //        ApplicationContext appCtx = ApplicationContextUtil.getApplicationContext();
17 //        logger.debug(appCtx);
18 //        if(appCtx==null)
19 //        {
20 //            logger.debug("ApplicationContext  为空");
21 //        }
22
23         System.out.println(orderStatisticsOperator);
24         System.out.println("===========暂无问题===============");
25         orderStatisticsList= orderStatisticsOperator.selectOrdersInfoByToday(DateTimeTool.get_now_date());
26         System.out.println("============end===============");
27     }

之后运行:

方法三:使用ApplicationContextUtil,继承ApplicationContextAware,并且创建新的服务层接口

   这个时候,需要再创建一个新的接口:OrderStatisticsInterface

 1 package service.statistics;
 2 import java.util.List;
 3
 4 import org.springframework.beans.factory.annotation.Autowired;
 5 import org.springframework.stereotype.Service;
 6
 7 import pojo.part.OrderStatisticsPart;
 8 import mapper.part.OrderStatisticsPartMapper;
 9
10 /**
11  * @author zyr
12  * 按日期查询当天商城消费订单信息
13  */
14 public interface OrderStatisticsInterface {
15
16     public List<OrderStatisticsPart> selectOrdersInfoByToday(String today_date);
17 }

然后在刚刚的service中继承该接口:

 1 package service.timer;
 2 import java.util.ArrayList;
 3 import java.util.List;
 4
 5 import mapper.DishSaleStatisticsMapper;
 6 import mapper.part.OrderStatisticsPartMapper;
 7
 8 import org.apache.log4j.Logger;
 9 import org.springframework.beans.factory.annotation.Autowired;
10 import org.springframework.context.ApplicationContext;
11 import org.springframework.context.annotation.Configuration;
12 import org.springframework.scheduling.annotation.Scheduled;
13 import org.springframework.stereotype.Component;
14 import org.springframework.stereotype.Service;
15
16 import pojo.part.OrderDetailStatisticsPart;
17 import pojo.part.OrderStatisticsPart;
18 import service.statistics.DishSaleStatisticsOperator;
19 import service.statistics.OrderDetailStatisticsOperator;
20 import service.statistics.OrderStatisticsInterface;
21 import service.statistics.OrderStatisticsOperator;
22 import service.statistics.ShopSaleStatisticsOperator;
23 import service.statistics.WaitingTimeStatisticsOperator;
24 import tools.time.DateTimeTool;
25
26 package service.statistics;
27 import java.util.List;
28
29 import javax.transaction.Transactional;
30
31 import org.springframework.beans.factory.annotation.Autowired;
32 import org.springframework.stereotype.Service;
33
34 import pojo.part.OrderStatisticsPart;
35 import mapper.part.OrderStatisticsPartMapper;
36
37 /**
38  * @author zyr
39  * 按日期查询当天商城消费订单信息
40  */
41 @Service("orderStatisticsInterface")
42 public class OrderStatisticsOperator implements OrderStatisticsInterface{
43     @Autowired
44     private OrderStatisticsPartMapper orderStatisticsPartMapper;
45         @Override
46     public List<OrderStatisticsPart> selectOrdersInfoByToday(String today_date) {
47          return orderStatisticsPartMapper.selectOrdersInfoByToday(today_date);
48     }
49 }

最后在timer中:

 1   where pay_time like ‘#{today_date,jdbcType = VARCHAR}%‘
 2
 3
 4 package service.timer;
 5 import java.util.ArrayList;
 6 import java.util.List;
 7
 8 import mapper.DishSaleStatisticsMapper;
 9 import mapper.part.OrderStatisticsPartMapper;
10
11 import org.apache.log4j.Logger;
12 import org.springframework.beans.factory.annotation.Autowired;
13 import org.springframework.context.ApplicationContext;
14 import org.springframework.context.annotation.Configuration;
15 import org.springframework.scheduling.annotation.Scheduled;
16 import org.springframework.stereotype.Component;
17 import org.springframework.stereotype.Service;
18
19 import pojo.part.OrderDetailStatisticsPart;
20 import pojo.part.OrderStatisticsPart;
21 import service.statistics.DishSaleStatisticsOperator;
22 import service.statistics.OrderDetailStatisticsOperator;
23 import service.statistics.OrderStatisticsInterface;
24 import service.statistics.OrderStatisticsOperator;
25 import service.statistics.ShopSaleStatisticsOperator;
26 import service.statistics.WaitingTimeStatisticsOperator;
27 import tools.time.DateTimeTool;
28
29 /**
30  * @author zyr
31  * 系统定时器,每一天定时运行一次,进行统计工作
32  */
33 @Component
34 public class StatisticsTimer {
35     private static Logger logger = Logger.getLogger(StatisticsTimer.class);
36     //一次性查询所有的订单相关信息
37     private List<OrderStatisticsPart> orderStatisticsList = new ArrayList<OrderStatisticsPart>();
38      //定时器测试
39     @Scheduled(cron="0/20 * *  * * ? ")
40     public void statisticsTimerCycle(){
41         System.out.println("============begining===============");
42         //按时间查询该天商城的所用订单,返回订单的中需要用到的字段,实现统计功能
43         ApplicationContext appCtx = ApplicationContextUtil.getApplicationContext();
44         logger.debug(appCtx);
45         if(appCtx==null)
46         {
47             logger.debug("ApplicationContext  为空");
48         }
49         OrderStatisticsInterface orderStatisticsInterface=(OrderStatisticsInterface)ApplicationContextUtil.getBean("orderStatisticsInterface");
50         System.out.println(orderStatisticsInterface);
51         System.out.println("===========暂无问题===============");
52         orderStatisticsList= orderStatisticsInterface.selectOrdersInfoByToday(DateTimeTool.get_now_date());
53         System.out.println("============end===============");
54     }

结果为:

综上所述,这就是我这一天多完成的任务了,虽然遇到了困难,并且放大了困难,也确实学到了一些好的方法,算是为自己对springmvc和Spring的理解创造了条件,奠定了坚实的基础,对于组件扫描,以及定时器的操作有了更深刻的认识,希望能对读者有意义,帮助大家解决一定的问题,可以看到我陈述解决问题的时候,非常的细腻,不漏过任何的东西,这也是很多博客做不到的,只专注于一件事情,并且做到最好,让大家可以照着做一遍,而不是一知半解!

时间: 2024-10-13 05:42:44

又是一个愚蠢的错误,皆因.xml而起的相关文章

犯了一个愚蠢的错误

/** * @author kc *  */public class UrlAccessFilter implements Filter { private InputStream path; public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response,   FilterCh

坑爹的Hibernate 映射文件错误提示org.xml.sax.SAXParseException

今天整整一个上午都在和hibernate做斗争,早上一来,继续昨天的项目开发,发现spring项目不能启动,从错误中看是hibernate错误,多半是hibernate配置有错误,关键是错误提示中显示“com.mdnet.travel.core.dao.ValidCodeDAOImpl”不能注入,经过仔细查看未见异常,而且这个文件好久没有改过了.没办法把hibernate的配置改成如下配置: <bean id="sessionFactory" class="org.sp

转载:sax错误:org.xml.sax.SAXParseException: Content is not allowed in prolog解决

原因及其解决办法: 1.xml编码错误 该xml是UTF-8编码的,如果该文件通过UltraEdit编辑后,会在无BOM头的UTF-8文件中加入BOM,但是DOM4j不认这个BOM(dom4j1.3),解决的办法可以通过升级dom4j到1.6解决www.dom4j.org 什么是BOM?http://www.unicode.org/faq/utf_bom.html#22Unicode规范中有一个BOM的概念.BOM——Byte Order Mark,就是字节序标记.在这里找到一段关于BOM的说明

2019渐渐走到终点,又是一个总结与展望的时刻

2019渐渐走到终点,又是一个总结与展望的时刻. 入行多年,一路走来看到身边的产品经理们一直有各种各样的迷茫,特写一篇修炼指南,为大家2020年的修炼提供一些参考. 你是不是也有过这样的困惑: 程序猿们说“这需求技术上做不了”,咋办?另外感觉他们的估时好像特不靠谱,可我刚张嘴他们就说“U can U up”,秒怂……四面八方的业务需求提过来,说得天花乱坠,怎么知道做出来有没有用?有的业务一拒绝就吵,还找领导,怎么办?有些需求完全不符合我的产品原则,比如到处挖坑塞广告位加营销资源位,但业务说是为了

个人犯的一个golang routine错误

认识golang也不少时间了,也做过几个项目.最近发现之前用golang写的一个服务,内存涨得比较快,一直没找出来原因来.今天把疑惑发到群里,经过golang学习班的童鞋的指点,发现我一个常用的错误. 在不少golang入门的文章上,用并发的例子一般是这样写的: package main import ( "fmt" "time" ) func main() { messages := make(chan int) go func() { time.Sleep(ti

苹果平板的按键和电源接线放在一个地方是一个最大的错误

苹果平板的按键和电源接线放在一个地方是一个最大的错误,为什么?我崽使用了一年,电源线接触不良了,要按着按键才能充电.这说明焊锡有松脱问题了.要么电源插口放在别处,不与按键放一处,要么采用感应式的软按键---和案桌的一样,最好是两个方案并用.这维修很复杂的.就拆都够费劲的了,还有焊锡.暗脱的焊锡更烦,还得测电阻. 联想YOGA Tablet 8在这方面考虑比较好.如何再冗余一个专用圆口充电接口就更漂亮了,毕竟充电接口是用的最频繁的了.---两三千的用一年就接触不良的使用体验绝对是一个很差的体验.

又是一个夏天要过去了

似乎我能列出这十一年中每一个夏天和它们离开的时候. 而这一年的,也快了. 十一年前的洪水,逃离是开始,而整个夏天充满欢乐,有亲爱的伙伴和儿时的熟悉的家属区和在里面一起玩闹的场景.虽然排斥畏惧和埋怨着它的炎热,却又享受着它的欢乐.而秋意的来临则是它的结束. 而十年前的夏天已经记不得了,只记得夏天结束时的那棵白杨树.在树下犹豫了很久后做出了最后的选择,一家人的生活就变了节奏.还记得在家乡县城中医院附近租住的小房间,那时已经全是秋意了.而如今转眼十年都过去了. 中间略过很多年.而表哥书橱里的书在很早的

关于启动 SecureCRT 遇到一个致命的错误且必须关闭

--------------------------SecureCRT---------------------------SecureCRT 遇到一个致命的错误且必须关闭. 一个崩溃转储文件已创建于: C:\Users\Administrator\AppData\Roaming\SecureCRT.dmp 请提交一个 bug 报告给 VanDyke Software, Inc. 的技术支持,, 使用以下的 URL 地址: 你将收到如何发送崩溃转储文件的说明. (此信息的内容可以通过 CTRL+

再论:p2p风控是p2p网站的核心——这又是一个文盲式屁话

全国上下,从政府到民间,所谓的专家和投资人基本都认为,p2p风控是p2p理财网站的核心,经过近来本人热心关注和常年互联网经验,我认为这又是一个文盲式屁话! 说出这样的话,基本上是不懂互联网的人或者是懂又不懂的那种"庸才",都被定性的思维模式和传统的观念束缚了. 在互联网思维中,风控只是互联网经营中重要的一个环节,而不是核心和重心. 如果非要说核心的话,那可以片面的说下,p2p理财模式和经营模式或者更确切的说人才模式才是核心. 互联网的基因是什么,她与生俱来就伴随着高风险高回报高损失而产