SpringBoot自定义配置以及拦截器配置

作者: HikariCP | 来源:发表于2017-11-06 02:22 被阅读3143次

    在进行 SpringBoot 项目开发的过程中,对于 SpringBoot 自带的默认配置我们难免有自己不喜欢的地方。或者你认为更合理更想要的处理方式,这种时候你就可以选择配置自己的处理逻辑。

    如果Spring Boot提供的Sping MVC不符合要求,则可以通过一个配置类(注解有@Configuration的类)加上@EnableWebMvc注解来实现完全自己控制的MVC配置。

    @EnableWebMvc
    @Configuration
    public class TestMvc {
        ···
    }
    

    通常情况下,Spring Boot的自动配置是符合我们大多数需求的。在你既需要保留Spring Boot提供的便利,有需要增加自己的额外的配置的时候,可以定义一个配置类并继承WebMvcConfigurerAdapter,无需使用@EnableWebMvc注解。

    @Configuration
    public class TestMvc extends WebMvcConfigurerAdapter{
        ···
    }
    

    这里我们提到这个WebMvcConfigurerAdapter这个类,重写这个类中的方法可以让我们增加额外的配置,常用的有如下几个。


    自定义资源映射 addResourceHandlers

    如果想自定义静态资源映射目录的话,只需重写WebMvcConfigurerAdapter类的addResourceHandlers方法即可。

    /**
    * {@inheritDoc}
    * <p>This implementation is empty.
    *
    * @param registry
    */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/illuos1ion/**").addResourceLocations("classpath:/illuos1ion/");
            super.addResourceHandlers(registry);
     }
    
    / ========================================================================================= /
      
    // WebMvcAutoConfiguration 
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
           if(!this.resourceProperties.isAddMappings()) {
                    logger.debug("Default resource handling disabled");
                } else {
                    Integer cachePeriod = this.resourceProperties.getCachePeriod();
                    if(!registry.hasMappingForPattern("/webjars/**")) {
                        this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(cachePeriod));
                    }
    
                    String staticPathPattern = this.mvcProperties.getStaticPathPattern();
                    if(!registry.hasMappingForPattern(staticPathPattern)) {
                        this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(this.resourceProperties.getStaticLocations()).setCachePeriod(cachePeriod));
                    }
    
           }
    }
    
    • 通过addResourceHandler添加映射路径,然后通过addResourceLocations来指定资源文件路径。
    • 访问自定义illuos1ion文件夹中的 item-video.png 图片的地址为 http://localhost:8080/illuos1ion/item-video.png

    如果想指定外部的文件目录也很简单,直接通过addResourceLocations方法指定即可:

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/my/**").addResourceLocations("file:E:/illuos1ion/");
        super.addResourceHandlers(registry);
    }
    
    • addResourceLocations 指的是文件放置的目录,addResoureHandler 指的是对外暴露的访问路径

    页面跳转 addViewControllers

    重写 WebMvcConfigurerAdapter 中的 addViewControllers 方法即可达到你想要的处理效果:

    /**
         * 过去要访问一个页面需要先创建个Controller控制类,再写方法跳转到页面
         * 在这里配置后就不需要那么麻烦了,直接访问http://localhost:8080/toLogin就跳转到login.jsp页面了
         * @param registry
         */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/toLogin").setViewName("login");
        super.addViewControllers(registry);
    }
    

    需要注意的是,在这里重写addViewControllers方法,并不会覆盖WebMvcAutoConfiguration中的addViewControllers(在此方法中,Spring Boot将“/”映射至index.html),这也就意味着我们自己的配置和Spring Boot的自动配置同时有效。


    拦截器addInterceptors

    拦截器在项目中经常使用的,这里介绍下最简单的判断是否登录的使用。
    要实现拦截器功能需要完成2个步骤:

    • 创建自己的拦截器类并实现 HandlerInterceptor 接口
    • 重写WebMvcConfigurerAdapter类中的addInterceptors方法把自定义的拦截器类添加进来即可

    拦截器代码:

    @Component
    public class LoginInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            boolean flag;
            User user = (User) request.getSession().getAttribute("user");
            if (user == null) {
                response.sendRedirect("/login");
                flag = false;
            } else {
                flag = true;
            }
            return flag;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    
        }
    }
    
    1. 这里简单实现了根据session中是否有User对象来判断是否登录,为空就跳转到登录页,不为空就通过。
    2. 接着,重写WebMvcConfigurerAdapter类中的addInterceptors方法:

    Web配置代码:

    @Configuration
    public class WebMvcConfiguration extends WebMvcConfigurerAdapter{
    
        @Autowired
        LoginInterceptor loginInterceptor;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            // addPathPatterns 用于添加拦截规则
            // excludePathPatterns 用户排除拦截
            // 映射为 user 的控制器下的所有映射
     registry.addInterceptor(loginInterceptor).addPathPatterns("/login/home").excludePathPatterns("/index", "/");
            super.addInterceptors(registry);
        }
    }
    

    拦截器执行流程参考:http://www.jianshu.com/p/f14ed6ca4e56

    addPathPatterns("/login/home")/login/home请求拦截,但是排除了/index/请求的拦截。


    Html登录代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8"/>
        <title>Login</title>
        <link rel="stylesheet" href="/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css"/>
        <script type="text/javascript" src="/webjars/jquery/3.2.1/jquery.min.js"></script>
    </head>
    <body>
    <form class="form-horizontal" role="form" method="post" action="/login/process">
        <div class="form-group">
            <!--<span class="input-group-addon">用户名</span>-->
            <label class="control-label col-sm-2" for="username">用户名:</label>
            <div class="col-sm-10">
                <input type="text" id="username" name="username" class="form-control" placeholder="Username"/>
            </div>
        </div>
    
        <div class="form-group">
            <!--<span class="input-group-addon">密码</span>-->
            <label class="control-label col-sm-2" for="password">密  码:</label>
            <div class="col-sm-10">
                <input type="text" id="password" name="password" class="form-control" placeholder="Password"/>
            </div>
        </div>
    
        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <button type="submit" class="btn btn-info">登 录</button>
                <button type="submit" class="btn btn-info">注 册</button>
            </div>
        </div>
    
    </form>
    </body>
    </html>
    

    控制器代码:

    @Controller
    @RequestMapping(path = "/login")
    public class LoginController {
    
        @RequestMapping(path = "/process", method = RequestMethod.POST)
        public String login(@RequestParam String username,
                            @RequestParam String password,
                            HttpServletRequest request) {
            if (username.equals("admin") && password.equals("admin")) {
                User user = new User(username, password, "http://www.jiyongguang.xin");
                request.getSession().setAttribute("user", user);
                return "redirect:/login/home";
            }
            return "redirect:/";
        }
    
        @RequestMapping(path = "/home", method = RequestMethod.GET)
        public String home(Model model) {
            List<User> userList = new ArrayList<User>();
            User user = new User("jyg", "jyg", "http://www.jiyongguang.xin");
            userList.add(user);
    
            user = new User("lyn", "lyn", "http://www.jiyongguang.xin");
            userList.add(user);
            model.addAttribute("userList", userList);
            return "home";
        }
    }
    

    或者可以通过Jquery封装好的AJAX方法来执行一套请求。效果是一样的

    $(document).ready(function () {
            $("#login").click(function () {
                $.ajax({
                    type: "POST",
                    url: "/login/process",
                    data: {
                        username: $("#username").val(),
                        password: $("#password").val()
                    },
                    dataType: "json",
                    success: function (data) {
                        if (data.code == 1)
                            <!-- 当前页面打开URL页面 -->
                            window.location.href = "/login/home";
                        else
                            alert("账号密码不能为空!");
                    }
                });
            });
    });
    

    控制器代码:

    @RequestMapping(value = "/process", method = RequestMethod.POST)
    @ResponseBody
    public String index(@RequestParam String username,
                        @RequestParam String password,
                        HttpServletRequest request) {
            Map<String, Object> map = new HashMap<String, Object>();
            if (username.equals("admin") && password.equals("admin")) {
                User user = new User(username, password, "http://www.jiyongguang.xin");
                request.getSession().setAttribute("user", user);
                return JsonUtil.getJsonString(JsonUtil.REQUEST_SUCCESS);
            } else {
                return JsonUtil.getJsonString(JsonUtil.REQUEST_Fail, "用户名或密码错误");
            }
    }
    

    这样访问/login/home的时候,如果未登录就会跳转到login.html页面(注意缓存),而访问http://localhost:8080/indexhttp://localhost:8080不会被拦截。

    更多配置可以查看WebMvcConfigurerAdapter的类的API。因其是WebMvcConfigurer接口的实现,所以WebMvcConfigurer的API方法也可以用来配置MVC。只是实现这个接口的话,要实现所有的方法,这个就比较麻烦了。所以还是推荐使用继承WebMvcConfigurerAdapter类来处理。

    相关文章

      网友评论

        本文标题:SpringBoot自定义配置以及拦截器配置

        本文链接:https://www.haomeiwen.com/subject/zwjkmxtx.html