最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot視圖解析實現(xiàn)原理深入分析

 更新時間:2022年10月08日 10:09:02   作者:Decade0712  
視圖解析其實就是SpringBoot某一個controller的方法執(zhí)行完成之后,它是跳轉到那個頁面。由于我們springboot項目默認打包為jar包,是形成壓縮包的形式,而jsp又不支持壓縮,所以我們SpringBoot不知JSP的,需要引入第三方模板引擎才可以處理

一、寫在前面

前面我們分析了Spring boot是如何解析請求參數(shù)和如何處理相應信息的

那么它是如何進行視圖解析,找到我們要跳轉的視圖并進行視圖渲染的呢?

二、寫個demo

為了研究視圖解析原理,我們寫一個測試代碼

首先是控制器類IndexController.java

package com.decade.controller;
import com.decade.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import javax.servlet.http.HttpSession;
@Controller
public class IndexController {
    /**
     * 來登錄頁
     * @return 跳轉登錄頁
     */
    @GetMapping(value = {"/","/login"})
    public String loginPage(){
        return "login";
    }
    @PostMapping("/login")
    public String main(User user, HttpSession session, Model model){
        if(StringUtils.hasLength(user.getUserName()) && "123456".equals(user.getPassword())){
            //把登陸成功的用戶保存到session中
            session.setAttribute("loginUser", user);
            //登錄成功重定向到main.html;  重定向防止刷新首頁時表單重復提交
            return "redirect:/main.html";
        }else {
            model.addAttribute("msg","賬號密碼錯誤");
            //回到登錄頁面
            return "login";
        }
    }
    /**
     * 去main頁面
     * @return 跳轉主頁面
     */
    @GetMapping("/main.html")
    public String mainPage(HttpSession session,Model model){
        //是否登錄。  攔截器,過濾器
        Object loginUser = session.getAttribute("loginUser");
        if(loginUser != null){
            return "main";
        }else {
            //回到登錄頁面
            model.addAttribute("msg","請重新登錄");
            return "login";
        }
    }
}

login.html放于templates文件夾下

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
    <meta name="description" content="">
    <meta name="author" content="ThemeBucket">
    <link rel="shortcut icon" href="#" rel="external nofollow"  type="image/png">
    <title>Login</title>
    <link href="css/style.css" rel="external nofollow"  rel="stylesheet">
    <link href="css/style-responsive.css" rel="external nofollow"  rel="stylesheet">
    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!--[if lt IE 9]>
    <script src="js/html5shiv.js"></script>
    <script src="js/respond.min.js"></script>
    <![endif]-->
</head>
<body class="login-body">
<div class="container">
    <form class="form-signin" action="index.html" method="post" th:action="@{/login}">
        <div class="form-signin-heading text-center">
            <h1 class="sign-title">Sign In</h1>
            <img src="images/login-logo.png" alt=""/>
        </div>
        <div class="login-wrap">
            <label style="color: red" th:text="${msg}"></label>
            <input type="text" name="userName" class="form-control" placeholder="User ID" autofocus>
            <input type="password" name="password" class="form-control" placeholder="Password">
            <button class="btn btn-lg btn-login btn-block" type="submit">
                <i class="fa fa-check"></i>
            </button>
            <div class="registration">
                Not a member yet?
                <a class="" href="registration.html" rel="external nofollow" >
                    Signup
                </a>
            </div>
            <label class="checkbox">
                <input type="checkbox" value="remember-me"> Remember me
                <span class="pull-right">
                    <a data-toggle="modal" href="#myModal" rel="external nofollow" > Forgot Password?</a>
                </span>
            </label>
        </div>
        <!-- Modal -->
        <div aria-hidden="true" aria-labelledby="myModalLabel" role="dialog" tabindex="-1" id="myModal" class="modal fade">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                        <h4 class="modal-title">Forgot Password ?</h4>
                    </div>
                    <div class="modal-body">
                        <p>Enter your e-mail address below to reset your password.</p>
                        <input type="text" name="email" placeholder="Email" autocomplete="off" class="form-control placeholder-no-fix">
                    </div>
                    <div class="modal-footer">
                        <button data-dismiss="modal" class="btn btn-default" type="button">Cancel</button>
                        <button class="btn btn-primary" type="button">Submit</button>
                    </div>
                </div>
            </div>
        </div>
        <!-- modal -->
    </form>
</div>
<script src="js/jquery-1.10.2.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/modernizr.min.js"></script>
</body>
</html>

三、流程解析

我們在登錄頁隨機輸入用戶名和錯誤的密碼,然后點擊登錄

我們跟蹤斷點,他還是進入到DispatcherServlet這個類下的doDispatch()方法

然后我們走到RequestMappingHandlerAdapter類下的handleInternal()—>invokeHandlerMethod()

設置參數(shù)解析器和返回值處理器

在這里,它就會走到ServletInvocableHandlerMethod類下的invokeAndHandle()方法,通過this.invokeForRequest(webRequest, mavContainer, providedArgs)去調用控制器類中的具體方法

我們發(fā)現(xiàn),如果方法的參數(shù)是一個自定義類型對象(例如demo中的User),調用完具體方法后,我們會把他放在ModelAndViewContainer中

斷點繼續(xù)深入,我們走到了HandlerMethodReturnValueHandlerComposite類下的handleReturnValue(),這里它會使用this.selectHandler(returnValue, returnType)去獲取自己適合的返回值解析器

然后我們進入到ViewNameMethodReturnValueHandler這個返回值解析器

public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
    if (returnValue instanceof CharSequence) {
    	// 獲取視圖名稱
        String viewName = returnValue.toString();
        mavContainer.setViewName(viewName);
        // 判斷是否是重定向頁面
        if (this.isRedirectViewName(viewName)) {
            mavContainer.setRedirectModelScenario(true);
        }
    } else if (returnValue != null) {
        throw new UnsupportedOperationException("Unexpected return type: " + returnType.getParameterType().getName() + " in method: " + returnType.getMethod());
    }
}

重點:我們可以發(fā)現(xiàn),目標方法處理的過程中,所有數(shù)據(jù)都會被放在 ModelAndViewContainer 里面。包括數(shù)據(jù)和視圖地址

經(jīng)過上述處理之后,我們返回到RequestMappingHandlerAdapter類中

ModelAndView var15 = this.getModelAndView(mavContainer, modelFactory, webRequest);

這行代碼會將ModelAndViewContainer 中的數(shù)據(jù)放到ModelAndView中

然后返回到DispatcherServlet這個類中,處理派發(fā)結果(頁面該如何響應)的關鍵代碼this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);

我們進入該方法進行分析

this.render(mv, request, response); 進行頁面渲染邏輯

String viewName = mv.getViewName();獲取視圖名稱

view = this.resolveViewName(viewName, mv.getModelInternal(), locale, request);循環(huán)遍歷當前系統(tǒng)中所有的視圖解析器嘗試是否能根據(jù)當前返回值得到View對象,符合條件的視圖解析器為ContentNegotiatingViewResolver(ContentNegotiationViewResolver 里面包含了下面所有的視圖解析器,內部還是利用下面所有視圖解析器得到視圖對象),最后返回的視圖對象為ThymeleafView

下面是幾種不同返回值所對應的視圖對象

  • 返回值以 forward: 開始: new InternalResourceView(forwardUrl); —> 轉發(fā),底層為request.getRequestDispatcher(path).forward(request, response);
  • 返回值以 redirect: 開始: new RedirectView() —> render底層就是重定向
  • 返回值是普通字符串: new ThymeleafView()—>通過對應的解析處理,并通過writer輸出流寫出到頁面

然后通過view.render(mv.getModelInternal(), request, response);調用視圖對象自定義的render進行頁面渲染工作

大家也可以輸入正確的用戶名和密碼,debug一下重定向是如何解析的

到此這篇關于SpringBoot視圖解析實現(xiàn)原理深入分析的文章就介紹到這了,更多相關SpringBoot視圖解析內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • JAVA Iterator接口與增強for循環(huán)的實現(xiàn)

    JAVA Iterator接口與增強for循環(huán)的實現(xiàn)

    這篇文章主要介紹了JAVA Iterator接口與增強for循環(huán)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • Spring Boot使用RestTemplate消費REST服務的幾個問題記錄

    Spring Boot使用RestTemplate消費REST服務的幾個問題記錄

    這篇文章主要介紹了Spring Boot使用RestTemplate消費REST服務的幾個問題記錄,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • Java WeakHashMap案例詳解

    Java WeakHashMap案例詳解

    這篇文章主要介紹了Java WeakHashMap案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-08-08
  • java8新特性之日期時間API

    java8新特性之日期時間API

    這篇文章主要介紹了java8新特性之日期時間API,文中有非常詳細的代碼示例,對正在學習java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • idea中導入別人的springboot項目的方法(圖文)

    idea中導入別人的springboot項目的方法(圖文)

    這篇文章主要介紹了idea中導入別人的springboot項目的方法(圖文),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • MyBatis Plus關閉SQL日志打印的方法

    MyBatis Plus關閉SQL日志打印的方法

    這篇文章主要介紹了MyBatis-Plus如何關閉SQL日志打印,文中通過圖文結合講解的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2024-02-02
  • SpringBoot實現(xiàn)定時發(fā)送郵件的三種方法案例詳解

    SpringBoot實現(xiàn)定時發(fā)送郵件的三種方法案例詳解

    這篇文章主要介紹了SpringBoot三種方法實現(xiàn)定時發(fā)送郵件的案例,Spring框架的定時任務調度功能支持配置和注解兩種方式Spring?Boot在Spring框架的基礎上實現(xiàn)了繼承,并對其中基于注解方式的定時任務實現(xiàn)了非常好的支持,本文給大家詳細講解,需要的朋友可以參考下
    2023-03-03
  • spring AOP的Around增強實現(xiàn)方法分析

    spring AOP的Around增強實現(xiàn)方法分析

    這篇文章主要介紹了spring AOP的Around增強實現(xiàn)方法,結合實例形式分析了spring面向切面AOP的Around增強具體步驟與相關操作方法,需要的朋友可以參考下
    2020-01-01
  • 老生常談java中的Future模式

    老生常談java中的Future模式

    下面小編就為大家?guī)硪黄仙U刯ava中的Future模式。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • Java中的setting和getting使用方法

    Java中的setting和getting使用方法

    為了保障數(shù)據(jù)的安全性,通常將數(shù)據(jù)成員定義為private(封裝或私有化),這樣外部代碼就無法直接訪問這些數(shù)據(jù),只能通過類提供的公共方法來進行訪問,這種方法主要包括setter和getter方法,以及構造方法,setter方法用于給私有屬性賦值
    2024-09-09

最新評論

苗栗市| 永丰县| 广水市| 方正县| 长兴县| 宜州市| 巢湖市| 留坝县| 依安县| 太和县| 庆安县| 南开区| 淮北市| 和顺县| 嵊州市| 库伦旗| 视频| 平顺县| 芜湖县| 天台县| 汝阳县| 沽源县| 白银市| 阳江市| 银川市| 新民市| 河东区| 九台市| 西贡区| 镇远县| 肥乡县| 乌兰察布市| 万安县| 克拉玛依市| 阿拉尔市| 修武县| 高邑县| 金山区| 陆河县| 游戏| 边坝县|