SpringBoot自定義配置以及攔截器配置

在進(jìn)行 SpringBoot 項目開發(fā)的過程中,對于 SpringBoot 自帶的默認(rèn)配置我們難免有自己不喜歡的地方。或者你認(rèn)為更合理更想要的處理方式,這種時候你就可以選擇配置自己的處理邏輯。

如果Spring Boot提供的Sping MVC不符合要求,則可以通過一個配置類(注解有@Configuration的類)加上@EnableWebMvc注解來實現(xiàn)完全自己控制的MVC配置。

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

通常情況下,Spring Boot的自動配置是符合我們大多數(shù)需求的。在你既需要保留Spring Boot提供的便利,有需要增加自己的額外的配置的時候,可以定義一個配置類并繼承WebMvcConfigurerAdapter,無需使用@EnableWebMvc注解。

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

這里我們提到這個WebMvcConfigurerAdapter這個類,重寫這個類中的方法可以讓我們增加額外的配置,常用的有如下幾個。


自定義資源映射 addResourceHandlers

如果想自定義靜態(tài)資源映射目錄的話,只需重寫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 指的是對外暴露的訪問路徑

頁面跳轉(zhuǎn) addViewControllers

重寫 WebMvcConfigurerAdapter 中的 addViewControllers 方法即可達(dá)到你想要的處理效果:

/**
     * 過去要訪問一個頁面需要先創(chuàng)建個Controller控制類,再寫方法跳轉(zhuǎn)到頁面
     * 在這里配置后就不需要那么麻煩了,直接訪問http://localhost:8080/toLogin就跳轉(zhuǎn)到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

攔截器在項目中經(jīng)常使用的,這里介紹下最簡單的判斷是否登錄的使用。
要實現(xiàn)攔截器功能需要完成2個步驟:

  • 創(chuàng)建自己的攔截器類并實現(xiàn) HandlerInterceptor 接口
  • 重寫WebMvcConfigurerAdapter類中的addInterceptors方法把自定義的攔截器類添加進(jìn)來即可

攔截器代碼:

@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. 這里簡單實現(xiàn)了根據(jù)session中是否有User對象來判斷是否登錄,為空就跳轉(zhuǎn)到登錄頁,不為空就通過。
  2. 接著,重寫WebMvcConfigurerAdapter類中的addInterceptors方法:

Web配置代碼:

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter{

    @Autowired
    LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // addPathPatterns 用于添加攔截規(guī)則
        // excludePathPatterns 用戶排除攔截
        // 映射為 user 的控制器下的所有映射
 registry.addInterceptor(loginInterceptor).addPathPatterns("/login/home").excludePathPatterns("/index", "/");
        super.addInterceptors(registry);
    }
}

攔截器執(zhí)行流程參考:http://www.lxweimin.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方法來執(zhí)行一套請求。效果是一樣的

$(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)
                        <!-- 當(dāng)前頁面打開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的時候,如果未登錄就會跳轉(zhuǎn)到login.html頁面(注意緩存),而訪問http://localhost:8080/indexhttp://localhost:8080不會被攔截。

更多配置可以查看WebMvcConfigurerAdapter的類的API。因其是WebMvcConfigurer接口的實現(xiàn),所以WebMvcConfigurer的API方法也可以用來配置MVC。只是實現(xiàn)這個接口的話,要實現(xiàn)所有的方法,這個就比較麻煩了。所以還是推薦使用繼承WebMvcConfigurerAdapter類來處理。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,908評論 6 541
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,324評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,018評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,675評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,417評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,783評論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,779評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,960評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,522評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,267評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,471評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,009評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,698評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,099評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,386評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,204評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,436評論 2 378

推薦閱讀更多精彩內(nèi)容