wilco的gravatar头像
wilco 2016-07-27 15:21:37

spring MVC项目中ThreadPoolTaskExecutor多线程注解为什么失败?

现web项目中存在一个正常的登陆功能,想在登陆的同时利用多线程添加一些额外的功能,代码如下:
controller:

    @ResponseBody
    @RequestMapping(value="/login",method=RequestMethod.POST)
    public Massage<UserBean> login(HttpServletRequest request,String name,String password) {
        Massage<UserBean> massage = loginService.login(name,password);
        //TODO 此处利用多线程记录日志操作
        return massage;
    }

service:

    @Override
    public Massage<UserBean> login(String name ,String password) {
        Massage<UserBean> massage = new Massage<UserBean>();
        UserBean user = userBeanMapper.selectByName(name);
        if (user == null) {
            massage.setSyscode("001");
            massage.setMsg("用户名称错误!");
            logger.info("登陆失败:" + "name("+name+")" +"用户名称错误!");
        }else if(!user.getPassword().equals(password)){
            massage.setSyscode("002");
            massage.setMsg("用户密码错误!");
            logger.info("登陆失败:" + "name("+name+")" +"用户密码错误!");
        }else{
            massage.setT(user);
            massage.setSyscode("000");
        }
        return massage;
    }

修改后:
controller:

    @ResponseBody
    @RequestMapping(value="/login",method=RequestMethod.POST)
    public Massage<UserBean> login(HttpServletRequest request,String name,String password) {
        Massage<UserBean> massage = loginService.login(name,password);
        //TODO 此处添加记录日志操作
        if("000".equals(massage.getSyscode())){//登陆成功
            WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
            ThreadPoolTaskExecutor threadPool = (ThreadPoolTaskExecutor) context.getBean("threadPool");
            threadPool.execute(new LoginRecordTask(name, massage.getSyscode()));
        }
        return massage;
    }
public class LoginRecordTask implements Runnable {

    private final static Logger logger = LoggerFactory.getLogger(LoginRecordTask.class);
    
    private String name;
    private String syscode;
    
    @Autowired
    private LoginService loginService;

    public LoginRecordTask(String name, String syscode) {
        super();
        this.name = name;
        this.syscode = syscode;
    }

    @Override
    public void run() {
        logger.info("登陆日志记录开始。。。");
        loginService.recordLogin(name);
        logger.info("登陆日志记录结束。。。");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSyscode() {
        return syscode;
    }

    public void setSyscode(String syscode) {
        this.syscode = syscode;
    }

}

 

测试发现:在LoginRecordTask中的loginService报了空指针,也就是未注入成功。。。

整了很久也没弄好,感谢知情者举手之劳!

所有回答列表(4)
最代码温柔的gravatar头像
最代码温柔  LV18 2016年7月28日

你方法是对的,问题就在于,你往spring web容器离注入的bean含有线程类。springIOC反转控住的实质就是预先加载(new Bean)类,等你用的时候直接@Autowired就可以了,线程类就有点特殊了。线程类有6个状态(new,runnable,block,waite,time_waite,terminated)。。。好了不说废话了,我直接贴图告诉你我怎么解决的吧,你在控制器了,直接new 出线程类,然后start就好了,我用的是单例模式,你可以参考一下spring MVC项目中ThreadPoolTaskExecutor多线程注解为什么失败?

这是我的线程类

spring MVC项目中ThreadPoolTaskExecutor多线程注解为什么失败?这是我的控制器

你上下文没有获取到线程类,所以你的注入报service空,然后longin task也是报空

评论(0) 最佳答案
zakari的gravatar头像
zakari  LV12 2016年7月27日

1.确定Spring配置文件中base-package扫描到了所有的文件:
<context:component-scan base-package=”文件扫描范围”>

2.换成这个注解试下 @Resource(name = "loginService")

gdwg2046的gravatar头像
gdwg2046  LV2 2016年7月29日

线程类要用sping管理起来,不然容器找不到。 你用aop记录日志不是挺好的吗

w341000的gravatar头像
w341000  LV2 2017年11月2日

你想让spring帮你注入属性,那么你的LoginRecordTask就不能在controller中自己new,而应该交给spring管理才对

顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友