拦截器失效,添加ComponentScan后,MyBatis获取不到Mapper解决方案

先扯两句

  既然前面已经开了这个先河,那闲着也是闲着,就把遇到的其他后台的问题也一并记录一下吧,说不好以后是不是用的上呢。

鸡贼

PS:你没看错,上面那张图就是鸡贼:


鸡贼翻译

鸡贼图片

正文

  我先把这个问题说一下,看看大家能不能看得明白,我自己都感觉像一个绕口令一样。

  首先,是我的拦截器设置了,但是并没有起到作用,调用接口还是直接进入到Controller中,于是搜索了一下网上的解决方案,给出的方案就是在拦截器添加@Component注解,并在Application添加@ComponentScan({"拦截器所在目录"})

import com.alibaba.fastjson.JSON;
import com.bsw.blog.annotation.LoginInterceptorWhitelist;
import com.bsw.blog.controller.UserController;
import com.bsw.blog.result.ResultBody;
import com.bsw.blog.result.ResultStateEnum;
import com.bsw.blog.util.Constants;
import com.bsw.blog.util.LogUtils;
import com.bsw.blog.util.TextUtils;
import com.bsw.blog.util.redis.Redis0Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 登录拦截器
 *
 * @author 半寿翁
 * @date 2020-8-31 20:15
 */
@Component
@Configuration
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    @Resource(name = "redis")
    private RedisTemplate stringRedisTemplate;

    /**
     * 日志打印
     */
    private final LogUtils log = new LogUtils(UserController.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 请求的方法是否有注解
        if (handler.getClass().isAssignableFrom(HandlerMethod.class)) {
            // 检测是否有 @OnlyAdmin 注解
            LoginInterceptorWhitelist oa = ((HandlerMethod) handler).getMethodAnnotation(LoginInterceptorWhitelist.class);
            log.i(request.getRequestURI() + request.getMethod());
            if (null == oa) {
                ...
            } else {
                return true;
            }
        }

        response.setStatus(401);
        response.sendError(401, "登录失效");

        ResultBody resultBody = new ResultBody(ResultStateEnum.RESULT_LOGIN_TIMEOUT);
        returnJson(response, JSON.toJSONString(resultBody));
        return false;
    }
}
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;

@SpringBootApplication(exclude = {
        RedisAutoConfiguration.class,
        RedisRepositoriesAutoConfiguration.class,
        DataSourceAutoConfiguration.class,
        DataSourceTransactionManagerAutoConfiguration.class
})
@ComponentScan("com.bsw.blog.interceptor"),
public class BlogApplication {
    public static void main(String[] args) {
        SpringApplication.run(BlogApplication.class, args);
    }
}

  满怀希望的运行一下,结果直接报错了,查看一下错误日志中的提示:

Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required

  于是去查,这个问题怎么解决,得到的方案是:

去掉@SpringBootApplication()的DataSourceAutoConfiguration.class

  于是把上面的代码Application的注解改成了

@SpringBootApplication(exclude = {
        RedisAutoConfiguration.class,
        RedisRepositoriesAutoConfiguration.class,
//        DataSourceAutoConfiguration.class,
        DataSourceTransactionManagerAutoConfiguration.class
})
@ComponentScan("com.bsw.blog.interceptor"),
public class BlogApplication {
    public static void main(String[] args) {
        SpringApplication.run(BlogApplication.class, args);
    }
}

  调整后重新编译,没一会就得到了新的报错,好兴奋啊,提示信息如下:

Consider the following:
 If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
 If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).

  有了新的错误,没关系,我们接着百度,果然得到了新的解决方案:

在@SpringBootApplication()添加上DataSourceAutoConfiguration.class,

  我TM,老子为了解决上一个问题,刚去掉,这就让我加回去。

没有口罩出去买

  纠结半天,终于想到办法,我还是叫外卖吧。。。通过查找@SpringBootApplication与@ComponentScan的冲突问题,终于看到了胜利的曙光——SpringBoot踩坑记录(@SpringBootApplication与@ComponentScan存在冲突)

(1)只有@SpringBootApplication,日志正常打印@SpringBootApplication默认会扫描同包及子包,所以TestController被扫描,打印日志
(2)存在@SpringBootApplication和一个@ComponentScan注解,不打印日志@ComponentScan注解会先被处理,然后返回,使得@SpringBootApplication中的配置没有生效
(3)存在@SpringBootApplication和多个@ComponentScan注解,日志正常打印

  所以在Application中做了如下调整:

@SpringBootApplication(exclude = {
        RedisAutoConfiguration.class,
        RedisRepositoriesAutoConfiguration.class,
        DataSourceAutoConfiguration.class,
        DataSourceTransactionManagerAutoConfiguration.class
})
@ComponentScans({
        @ComponentScan("com.bsw.blog.interceptor"),
        @ComponentScan("com.bsw.blog.mapper"),
})
public class BlogApplication {
    public static void main(String[] args) {
        SpringApplication.run(BlogApplication.class, args);
    }
}

  你没看错,就是添加了一条没有用的mapper的ComponentScans,然后项目真的正常运行了,啥也不说了,谁去给SpringBoot提个bug去。。。

鸣谢

  • 鸡贼:来自Pixabay的Ryan McGuire
  • 没有口罩出去买:来自出门买不到口罩,没口罩不能出门,我太难了

你可能感兴趣的:(拦截器失效,添加ComponentScan后,MyBatis获取不到Mapper解决方案)