SpringMVC_04_轉(zhuǎn)發(fā)重定向and全局異常處理and攔截器

四乳乌、SpringMVC核心技術(shù)

4.1 請(qǐng)求重定向

SpringMVC框架把原來Servlet表中的請(qǐng)求轉(zhuǎn)發(fā)和重定向操作進(jìn)行了封裝誉简,現(xiàn)在可以可以使用簡(jiǎn)單的方式實(shí)現(xiàn)轉(zhuǎn)發(fā)和重定向

forward:表示轉(zhuǎn)發(fā),實(shí)現(xiàn)request.getRequestDispatcher("xx.jsp").forward(request,response);镣丑,轉(zhuǎn)發(fā)在服務(wù)器內(nèi)部進(jìn)行操作唧取,一次請(qǐng)求

redirect:表示重定向航夺,實(shí)現(xiàn)response.sendRedirect("xxx.jsp"),用戶地址欄變化腥光,二次請(qǐng)求关顷,由于是用戶發(fā)起,不能訪問WEB-INF下的內(nèi)容

請(qǐng)求

格式:

modelAndView.setViewName("forward:/hello.jsp");

使用封裝的請(qǐng)求轉(zhuǎn)發(fā)武福,可以不通過視圖解析器解寝,這里路徑名使用的是全路徑名

轉(zhuǎn)發(fā)的顯示頁面可以自定義

案例:

請(qǐng)求頁面:

<p>SpringMVC封裝的請(qǐng)求轉(zhuǎn)發(fā)</p>
<form action="doForward.do" method="post">
 名稱:<input type="text" name="name"> <br>
 年齡:<input type="text" name="age"> <br>
 <input type="submit" value="提交">
</form>

后端控制器:

@Controller
public class MyController {
 @RequestMapping(value = "/doForward.do")
 public ModelAndView doForward(String name,String age){

 ModelAndView modelAndView = new ModelAndView();
 modelAndView.addObject("name","姓名 - " +name);
 modelAndView.addObject("age","年齡 - " + age);
 modelAndView.setViewName("forward:/hello.jsp");
 return modelAndView;
 }
}

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--    聲明注解掃描-->
 <context:component-scan base-package="com.GeekRose.controller"/>
<!--    聲明視圖解析器-->
 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
 <property name="prefix" value="/WEB-INF/view/"/>
 <property name="suffix" value=".jsp"/>
 </bean>
</beans>

顯示效果:

image-20211018125428178.png
重定向

重定向的語法格式:

modelAndView.setViewName("redirect:/hello.jsp");

實(shí)現(xiàn)重定向的步驟:

  1. 發(fā)出請(qǐng)求的前端資源
    <p>SpringMVC封裝的請(qǐng)求重定向</p>
    <form action="doRedirect.do" method="post">
     名稱:<input type="text" name="name"> <br>
     年齡:<input type="text" name="age"> <br>
     <input type="submit" value="提交">
    </form>
  1. 后端控制器接收請(qǐng)求,添加數(shù)據(jù)艘儒,請(qǐng)求重定向
    @RequestMapping("/doRedirect.do")
    public ModelAndView doRedirect(String name,String age){
    
     ModelAndView modelAndView = new ModelAndView();
     modelAndView.addObject("name","姓名 - " +name);
     modelAndView.addObject("age","年齡 - " + age);
     modelAndView.setViewName("redirect:/hello.jsp");
     return modelAndView;
    }
  1. 重定向頁面
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
     <title>顯示</title>
    </head>
    <body>
    <p>this is webapp / hello.jsp</p>
    
    得到的數(shù)據(jù): <br>
    name: ${name} <br>
    age: ${age} <br>
    
    </body>
    </html>
  1. 顯示效果:
image-20211019160139366.png
  1. 分析:

    • 請(qǐng)求重定向后頁面地址欄發(fā)生變化

    • 加入的數(shù)據(jù)沒有得到

    • 在地址欄中發(fā)現(xiàn)數(shù)據(jù)出現(xiàn)在地址欄的請(qǐng)求參數(shù)上

  2. 結(jié)論:

    請(qǐng)求重定向是兩次請(qǐng)求聋伦,request域中無法得到上一個(gè)request的數(shù)據(jù),重定向的頁面地址欄會(huì)變化界睁,加入的數(shù)據(jù)作為請(qǐng)求參數(shù)出現(xiàn)

  3. 得到數(shù)據(jù)的解決方案

    顯示頁面中將el表達(dá)式默認(rèn)request域改為從param參數(shù)中農(nóng)獲取

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
     <title>顯示</title>
    </head>
    <body>
    <p>this is webapp / hello.jsp</p>
    
    得到的數(shù)據(jù): <br>
    name: ${param.name} <br>
    age: ${param.age} <br>
    
    </body>
    </html>
  1. 顯示效果
image-20211019161139787.png

${param.name}相當(dāng)于

    數(shù)據(jù)相當(dāng)于:<%=request.getParameter("name")%>
  1. 當(dāng)我們要訪問WEB-INF下的數(shù)據(jù)觉增,會(huì)發(fā)生404

    重定向不能訪問受保護(hù)資源

框架對(duì)重定向的操作:

  1. 框架會(huì)把Model中的簡(jiǎn)單類型數(shù)據(jù),轉(zhuǎn)為string使用翻斟,作為hello.jsp的get請(qǐng)求參數(shù)使用

    目的:在doRedirect.do 和 hello.jsp兩次請(qǐng)求之間可以傳遞數(shù)據(jù)

  2. 在目標(biāo)hello.jsp頁面可以使用參數(shù)集合對(duì)象{param}獲取請(qǐng)求參數(shù)值逾礁,例如:{param.myname}

注意:

關(guān)鍵:SpringMVC的請(qǐng)求轉(zhuǎn)發(fā)和請(qǐng)求重定向不和視圖解析器一起使用


4.2 異常處理

業(yè)務(wù)功能和異常處理進(jìn)行解耦合,使用的aop思想访惜,SpringMVC框架采用的是統(tǒng)一全局異常處理方案嘹履,把Controller中的所有異常處理都集中到一個(gè)地方。采用的是aop的思想债热,把業(yè)務(wù)邏輯和異常處理代碼分開砾嫉。

使用兩個(gè)注解:

  1. @ExceptionHandler

  2. @ControllerAdvice

異常處理步驟:

  1. 新建Maven web項(xiàng)目

  2. 加入依賴

  3. 新建一個(gè)自定義異常類 MyUserException 再定義它的子類NameException AgeException

MyUserException

    public class MyUserException extends Exception{
     public MyUserException() {
     super();
     }
    
     public MyUserException(String message) {
     super(message);
     }
    }

NameException

    public class NameException extends MyUserException{
     public NameException() {
     super();
     }
    
     public NameException(String message) {
     super(message);
     }
    }

AgeException

    public class AgeException extends MyUserException{
     public AgeException() {
     super();
     }
    
     public AgeException(String message) {
     super(message);
     }
    }
  1. 在controller拋出NameException,AgeException
    @Controller
    public class MyController {
     @RequestMapping(value = "/doSome.do")
     public ModelAndView doSome(String name,Integer age) throws MyUserException {
    
     ModelAndView modelAndView = new ModelAndView();
     if (!"zs".equals(name)){
     throw new NameException("姓名不正確窒篱!");
     }
     if (age == null || age > 90){
     throw new AgeException("年齡不正確焕刮!");
     }
    
     modelAndView.addObject("name","姓名 - " +name);
     modelAndView.addObject("age","年齡 - " + age);

     modelAndView.setViewName("show");
     return modelAndView;
     }
    }
  1. 創(chuàng)建一個(gè)普通類舶沿,作用全局異常處理類

    1. 在類上面加入@ControllerAdvice

    2. 在類中定義方法,方法上面加入@ExceptionHandler

    //@ControllerAdvice 注解表示控制器通知 / 增強(qiáng)
    @ControllerAdvice
    public class GlobalExceptionHandler {
    
    //    @ExceptionHandler 注解映射解決具體異常的方法
     // 有一個(gè)參數(shù) 就是要解決異常的class類
     // 形參Exception配并,表示Controller中跑出的異常對(duì)象括荡,通過形參可以獲取發(fā)生的異常信息
     // 方法返回值和對(duì)應(yīng)的切入點(diǎn)的返回值一樣
     @ExceptionHandler(value = NameException.class)
     public ModelAndView doNameException(Exception ex){
     // 處理Name異常
     /*
     異常處理邏輯:
     1\. 需要把異常記錄下來,記錄到數(shù)據(jù)庫(kù)溉旋,日志文件
     記錄日志發(fā)生的時(shí)間畸冲,哪個(gè)方法發(fā)生的,異常錯(cuò)誤內(nèi)容
     2\. 發(fā)送通知观腊,把異常信息通過郵件 / 短信 / 微信發(fā)生給相關(guān)人員
     3\. 給用戶友好的提示
     */
     ModelAndView mv = new ModelAndView();
     mv.addObject("msg","姓名不準(zhǔn)確");
     mv.addObject("ex",ex);
     mv.setViewName("errorName");
     return mv;
     }
    
     @ExceptionHandler(value = AgeException.class)
     public ModelAndView doAgeException(Exception ex){
     ModelAndView mv = new ModelAndView();
     mv.addObject("msg","年齡不正確");
     mv.addObject("ex",ex);
     mv.setViewName("errorAge");
     return mv;
    
     }
     @ExceptionHandler
     public ModelAndView doOtherException(Exception ex){
     ModelAndView mv = new ModelAndView();
     mv.addObject("msg","這是其他類型的異常");
     mv.addObject("ex",ex);
     mv.setViewName("otherError");
     return mv;
     }
    }

當(dāng)我們的異常不是name和age產(chǎn)生召夹,即其他異常就會(huì)映射到不加value的@ExceptionHandler注解下的方法來處理

  1. 創(chuàng)建處理異常的視圖頁面

errorName.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
     <title>errorName</title>
    </head>
    <body>
    <h3>this is name error</h3>
    友情提示:${msg} <br>
    系統(tǒng)提示:${ex.message}
    </body>
    </html>

errorAge.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
     <title>errorAge</title>
    </head>
    <body>
    <h3>this is age error</h3>
    友情提示:${msg} <br>
    用戶提示:${ex.message}
    </body>
    </html>

otherError.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
     <title>other error</title>
    </head>
    <body>
    <h3>this is other error</h3>
    友情提示:${msg} <br>
    系統(tǒng)提示:${ex.message}
    </body>
    </html>
  1. 創(chuàng)建SpringMVC的配置文件

    1. 組件掃描器,掃描@Controller注解

    2. 組件掃描器恕沫,掃描@ControllerAdvice所在的包名

    3. 聲明注解驅(qū)動(dòng)

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:context="http://www.springframework.org/schema/context"
     xmlns:mvc="http://www.springframework.org/schema/mvc"
    
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
     http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--    聲明注解掃描-->
     <context:component-scan base-package="com.GeekRose.controller"/>
    <!--    聲明視圖解析器-->
     <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
     <property name="prefix" value="/WEB-INF/view/"/>
     <property name="suffix" value=".jsp"/>
     </bean>
    
    <!--    實(shí)現(xiàn)全局異常處理還需要兩步-->
     <mvc:annotation-driven />
     <context:component-scan base-package="com.GeekRose.handler" />
    </beans>

這里命名空間記得導(dǎo)入正確

  1. 效果:

當(dāng)我們輸入錯(cuò)誤數(shù)據(jù) 例如 姓名為zhangsan時(shí)

image-20211019180147911.png

得到的處理結(jié)果為:

image-20211019180204417.png

使用全局異常處理监憎,主要是為了實(shí)現(xiàn)解耦合,不用自己不斷寫try catch婶溯,異常處理代碼和業(yè)務(wù)邏輯代碼實(shí)現(xiàn)分離


4.3 攔截器

SpringMVC中的Interceptor攔截器是非常重要和相當(dāng)有用的鲸阔,它的主要作用是攔截指定的用戶請(qǐng)求,并進(jìn)行相應(yīng)的預(yù)處理和后處理迄委。其攔截的時(shí)間點(diǎn)在“處理器映射器根據(jù)用戶提交的請(qǐng)求映射出了所要執(zhí)行的處理器類褐筛,并且也找到了要執(zhí)行該處理器類的處理器適配器,在處理器適配器執(zhí)行處理器之前”叙身。當(dāng)然渔扎,在處理器映射器映射出所要執(zhí)行的處理器類時(shí),已經(jīng)將攔截器與處理器組合為了一個(gè)處理器執(zhí)行鏈信轿,并返回給了中央調(diào)度器晃痴。

實(shí)現(xiàn)了HandlerInterceptor接口的都是攔截器

攔截器和過濾器類似,但是側(cè)重點(diǎn)不同 功能方向不同财忽。

  • 過濾器用來過濾請(qǐng)求參數(shù)倘核,設(shè)置編碼字符集等工作。

  • 攔截器是攔截用戶的請(qǐng)求即彪,對(duì)請(qǐng)求做判斷處理的紧唱。

  • 攔截器是全局的,可以對(duì)多個(gè)Controller做攔截隶校。

    一個(gè)項(xiàng)目可以有0個(gè)或多個(gè)攔截器漏益,他們?cè)谝黄饠r截用戶的請(qǐng)求。

    攔截器常用在用戶登錄處理和權(quán)限檢查記錄日志深胳。

攔截器的使用步驟:

  1. 定義類實(shí)現(xiàn)HandlerInerterceptor接口

  2. 在SpringMVC配置文件中聲明攔截器绰疤,讓框架知道攔截器的存在

攔截器的執(zhí)行時(shí)間:

  1. 在請(qǐng)求處理之前,也就是controller類中的方法執(zhí)行之前先被攔截

  2. 在控制器方法執(zhí)行之后也會(huì)執(zhí)行攔截器

  3. 在請(qǐng)求處理完成后也會(huì)執(zhí)行攔截器

預(yù)處理方法
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 return false;
}

返回值:布爾值

  • true

  • false

方法參數(shù):

  • HttpServletRequest 請(qǐng)求

  • HttpServletResponse 響應(yīng)

  • Object Handler 處理器對(duì)象(MyController對(duì)象)

預(yù)處理方法在執(zhí)行處理器方法前執(zhí)行(MyController.doSome)稠屠,一般用作請(qǐng)求判斷峦睡,驗(yàn)證請(qǐng)求是否符合要求∪ú海可以驗(yàn)證用戶是否登錄榨了,驗(yàn)證用戶是否有權(quán)限訪問某個(gè)連接地址(URL)

如果驗(yàn)證失敗,可以截?cái)嗾?qǐng)求攘蔽,請(qǐng)求不能被處理

如果驗(yàn)證成功龙屉,可以方形請(qǐng)求,此時(shí)控制器方法才能執(zhí)行

后處理方法
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

}

返回值:void

方法參數(shù):

  • HttpServletRequest 請(qǐng)求

  • HttpServletResponse 響應(yīng)

  • Object handler 處理器對(duì)象

  • ModelAndView modelAndView 數(shù)據(jù)與視圖對(duì)象

后處理方法在處理器方法(MyController.doSome)執(zhí)行后執(zhí)行满俗,一般用作數(shù)據(jù)的二次修訂

最后執(zhí)行的方法
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

}

返回值:void

請(qǐng)求參數(shù):

  • HttpServletRequest 請(qǐng)求

  • HttpServletResponse 響應(yīng)

  • Object handler 處理器對(duì)象

  • Exception ex 異常對(duì)象

最后執(zhí)行的方法在請(qǐng)求完成后執(zhí)行(當(dāng)請(qǐng)求進(jìn)行forward转捕,發(fā)送到視圖時(shí)被認(rèn)定為請(qǐng)求完成),一般用作資源回收處理唆垃,程序中創(chuàng)建的一些對(duì)象在這里進(jìn)行刪除五芝,釋放占用的內(nèi)存

配置文件聲明攔截器

攔截器的聲明

<!--    聲明攔截器-->
 <mvc:interceptors>
 <mvc:interceptor>
<!--            映射地址 /** 表示工程目錄下的所有請(qǐng)求都會(huì)被攔截
 /user/** 表示user下的所有請(qǐng)求都會(huì)被攔截
-->
 <mvc:mapping path="/user/**"/>
 <bean class="com.GeekRose.interceptor.MyInterceptor" />
 </mvc:interceptor>
 </mvc:interceptors>

攔截器:看做多個(gè)Controller中公用的功能,集中到攔截器統(tǒng)一處理辕万,使用的aop思想

攔截器圖解:

image-20211020131724028.png
多個(gè)攔截器

多個(gè)攔截器的執(zhí)行順序

攔截器的執(zhí)行順序?yàn)閿r截器的聲明順序

圖解:

image-20211020133227066.png

當(dāng)我們定義兩個(gè)攔截器:

攔截器定義:

攔截器1:

package com.GeekRose.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
public class MyInterceptor1 implements HandlerInterceptor {
 private long btime;
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 System.out.println("MyInterceptor1-preHandle");

 return true;
 }

 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
 System.out.println("MyInterceptor1-postHandle");
 }

 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
 System.out.println("MyInterceptor1-afterCompletion");
 }
}

攔截器2:

package com.GeekRose.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
public class MyInterceptor2 implements HandlerInterceptor {
 private long btime;
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 System.out.println("MyInterceptor2-preHandle");
 return true;
 }

 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
 System.out.println("MyInterceptor2-postHandle");
 }

 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
 long etime = System.currentTimeMillis();
 System.out.println("MyInterceptor2-afterCompletion");
 }
}

攔截器聲明:

<!--    聲明攔截器-->
 <mvc:interceptors>
 <mvc:interceptor>
<!--            映射地址 /** 表示工程目錄下的所有請(qǐng)求都會(huì)被攔截
 /user/** 表示user下的所有請(qǐng)求都會(huì)被攔截
-->
 <mvc:mapping path="/user/**"/>
 <bean class="com.GeekRose.interceptor.MyInterceptor1" />
 </mvc:interceptor>
 <mvc:interceptor>
 <mvc:mapping path="/user/**"/>
 <bean class="com.GeekRose.interceptor.MyInterceptor2" />
 </mvc:interceptor>
 </mvc:interceptors>

兩個(gè)攔截器的預(yù)處理方法都為true

控制臺(tái)輸出:

MyInterceptor1-preHandle
MyInterceptor2-preHandle
---MyController-doSome---
MyInterceptor2-postHandle
MyInterceptor1-postHandle
MyInterceptor2-afterCompletion
MyInterceptor1-afterCompletion

多個(gè)攔截器執(zhí)行鏈:

image-20211020134206876.png

當(dāng)攔截器1的預(yù)處理方法為true枢步,攔截器2的預(yù)處理為false

處理結(jié)果:

MyInterceptor1-preHandle
MyInterceptor2-preHandle
MyInterceptor1-afterCompletion

攔截器1預(yù)處理為true,進(jìn)入攔截器2的預(yù)處理為false渐尿,此時(shí)無法進(jìn)行執(zhí)行醉途,截?cái)嗾?qǐng)求。因?yàn)閿r截器1的預(yù)處理為true砖茸,所以攔截器1的最終執(zhí)行方法會(huì)執(zhí)行隘擎。

當(dāng)攔截器1的預(yù)處理為false,攔截器2的預(yù)處理為true

處理結(jié)果:

MyInterceptor1-preHandle

直接截?cái)嗾?qǐng)求凉夯,不會(huì)到攔截器2

只要有一個(gè)攔截器為false货葬,請(qǐng)求到此結(jié)束不會(huì)到控制器中

攔截器和過濾器的區(qū)別
  1. 過濾器是Servlet規(guī)范中的對(duì)象,攔截器是框架中的對(duì)象

  2. 過濾器實(shí)現(xiàn)Filter接口的對(duì)象劲够,攔截器是實(shí)現(xiàn)HandlerInterceptor接口

  3. 過濾器用來設(shè)置request宝惰,response的參數(shù),屬性的再沧,側(cè)重對(duì)數(shù)據(jù)過濾的尼夺,攔截器是用來驗(yàn)證請(qǐng)求的脖苏,能截?cái)嗾?qǐng)求屏箍。

  4. 過濾器是在攔截器之前先執(zhí)行的

  5. 過濾器是tomcat服務(wù)器創(chuàng)建的對(duì)象,攔截器是SpringMVC容器中創(chuàng)建的對(duì)象

  6. 過濾器是一個(gè)執(zhí)行時(shí)間點(diǎn)

    攔截器有三個(gè)執(zhí)行時(shí)間點(diǎn)

  7. 過濾器可以處理jsp柬批、js顷扩、html等

    攔截器是側(cè)重?cái)r截對(duì)Controller的請(qǐng)求拐邪,如果你的請(qǐng)求不能被中央調(diào)度器接收,這個(gè)請(qǐng)求不會(huì)執(zhí)行攔截器內(nèi)容

  8. 攔截器攔截普通方法執(zhí)行隘截,過濾器過濾Servlet請(qǐng)求響應(yīng)

攔截器權(quán)限登錄案例

實(shí)現(xiàn)步驟:

  1. 新建maven項(xiàng)目

  2. 修改web.xml注冊(cè)中央調(diào)度器

  3. 新進(jìn)index.jsp發(fā)起請(qǐng)求

  4. 創(chuàng)建MyController處理請(qǐng)求

  5. 創(chuàng)建結(jié)果show.jsp

  6. 創(chuàng)建一個(gè)login.jsp扎阶,模擬登錄(把用戶信息放入session中)創(chuàng)建一個(gè)logout.jsp汹胃,模擬退出系統(tǒng)(從session中刪除數(shù)據(jù))

  7. 創(chuàng)建攔截器,從session中獲取用戶的登錄數(shù)據(jù)东臀,驗(yàn)證能否訪問系統(tǒng)

  8. 創(chuàng)建一個(gè)驗(yàn)證的jsp着饥,如果驗(yàn)證失敗,給出提示

  9. 創(chuàng)建springmvc配置文件

    聲明組件掃描器

    聲明攔截器

實(shí)現(xiàn)效果:

當(dāng)我們沒有登錄權(quán)限(session沒有數(shù)據(jù)時(shí))惰赋,會(huì)被攔截器階段請(qǐng)求調(diào)到提示頁面宰掉,當(dāng)我們有登錄權(quán)限,就會(huì)訪問到數(shù)據(jù)

這里登錄登出在jsp中實(shí)現(xiàn)

代碼實(shí)現(xiàn):

發(fā)出請(qǐng)求的index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<%
 String basePath = request.getScheme() + "://" + request.getServerName() + ":"
 + request.getServerPort() + request.getContextPath() + "/";
%>
<head>
 <title>Title</title>
 <base href="<%=basePath%>>">
</head>
<body>
<h3>這是主頁</h3>
<p>登錄驗(yàn)證</p>
<form action="user/doSome.do" method="post">
 名稱:<input type="text" name="name"> <br>
 年齡:<input type="text" name="age"> <br>
 <input type="submit" value="提交">
</form>

獲取登錄權(quán)限 login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
 <title>登錄</title>
</head>
<body>
<h3>log in</h3>
<%
 session.setAttribute("name","zs");
%>
</body>
</html>

登出刪除權(quán)限 logout.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
 <title>登出</title>
</head>
<h3>log out</h3>
<body>
<%
 session.removeAttribute("name");
%>
</body>
</html>

提示頁面 tips.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
 <title>Title</title>
</head>
<body>
你的請(qǐng)求已經(jīng)被FBI攔截赁濒,等著open the door吧
</body>
</html>

攔截器 MyInterceptor1

public class MyInterceptor1 implements HandlerInterceptor {
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

 Object key = request.getSession().getAttribute("name");
 String keyVal = (String) key;
 if (!"zs".equals(keyVal)){

 request.getRequestDispatcher("/tips.jsp").forward(request,response);
 return false;
 }
 return true;
 }
}

控制器

@Controller
@RequestMapping("/user")
public class MyController {
 @RequestMapping(value = "/doSome.do")
 public ModelAndView doSome(String name,Integer age) {
 System.out.println("---MyController-doSome---");
 ModelAndView modelAndView = new ModelAndView();

 modelAndView.addObject("name","姓名 - " +name);
 modelAndView.addObject("age","年齡 - " + age);

 modelAndView.setViewName("show");
 return modelAndView;
 }
}

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:mvc="http://www.springframework.org/schema/mvc"

 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
 http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--    聲明注解掃描-->
 <context:component-scan base-package="com.GeekRose.controller"/>
<!--    聲明視圖解析器-->
 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
 <property name="prefix" value="/WEB-INF/view/"/>
 <property name="suffix" value=".jsp"/>
 </bean>

 <mvc:annotation-driven />
<!--    聲明攔截器-->
 <mvc:interceptors>
 <mvc:interceptor>
<!--            映射地址 /** 表示工程目錄下的所有請(qǐng)求都會(huì)被攔截
 /user/** 表示user下的所有請(qǐng)求都會(huì)被攔截
-->
 <mvc:mapping path="/user/**"/>
 <bean class="com.GeekRose.interceptor.MyInterceptor1" />
 </mvc:interceptor>
 </mvc:interceptors>

</beans>

效果展示:

image-20211021122827187.png

沒有登錄權(quán)限:提交后

image-20211021122848132.png

獲取權(quán)限:

image-20211021122914131.png

此時(shí)我們?cè)龠M(jìn)行提交

image-20211021122930101.png

結(jié)果:

image-20211021122941710.png

當(dāng)我們刪除權(quán)限登出

image-20211021123005857.png

我們?cè)偬峤粩?shù)據(jù)

結(jié)果:

image-20211021123030607.png

4.4 SpringMVC的內(nèi)部處理流程

ApplicationContext ctx = new ClassPathXmlApplication("beans.xml");

StudentService service = (StudentService) ctx.getBean("service");

SpringMVC接收請(qǐng)求到處理完成的過程

  1. 用戶發(fā)起請(qǐng)求some.do

  2. DispatcherServlet接收請(qǐng)求some.do轨奄,把請(qǐng)求轉(zhuǎn)交給處理器映射器,

    處理器映射器是SpringMVC框架的一種對(duì)象拒炎,框架把實(shí)現(xiàn)了HandlerMapping接口的類都叫映射器

    處理器映射器作用:根據(jù)請(qǐng)求挪拟,從SpringMVC容器對(duì)象中獲取處理器對(duì)象(MyController controller = ctx.getBean("some.do"))

    框架把找到的處理器對(duì)象放到一個(gè)叫做處理器執(zhí)行鏈的類保存(HandlerExecutionChain)

    HandlerExectutionChain:類中保存著

    • 處理器對(duì)象(MyController)

    • 項(xiàng)目中所有的攔截器(List<HandlerInterceptor> interceptorList)

  3. DispatcherServlet把HandlerExecutionChain中的處理器對(duì)象交給了處理器適配器對(duì)象(多個(gè))

    處理器適配器是框架中的一種對(duì)象,是SpringMVC框架中的對(duì)象击你,需要實(shí)現(xiàn)HandlerAdapter接口

    處理器適配器作用:執(zhí)行處理器方法(調(diào)用MyController.doSome() 得到返回值ModelAndView)

    得到的結(jié)果再通過處理器適配器返回給中央調(diào)度器

  4. DispatcherServlet把3中獲取的ModelAndView交給視圖解析器對(duì)象

    視圖解析器:SpringMVC中的對(duì)象舞丛,需要實(shí)現(xiàn)ViewResolver接口(可以有多個(gè))

    視圖解析器作用:組成視圖完整路徑,使用前綴果漾、后綴球切,并創(chuàng)建View對(duì)象。view是一個(gè)接口绒障,表示視圖的吨凑,在框架中jsp、html不是string字符串表示户辱,而是使用view和它的實(shí)現(xiàn)類表示視圖

    InternalResourceView:視圖類鸵钝,表示jsp文件,視圖解析器會(huì)創(chuàng)建InternalResourceView類對(duì)象庐镐,這個(gè)對(duì)象里面恩商,有一個(gè)屬性u(píng)rl=/WEB-INF/view/show.jsp

  5. DispathcerServlet把4步驟中創(chuàng)建的View對(duì)象獲取到,調(diào)用View類自己的方法必逆,把Model數(shù)據(jù)放入到request作用域怠堪,執(zhí)行對(duì)象視圖的forward。請(qǐng)求結(jié)束

執(zhí)行流程圖解:

image-20211021130748705.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末名眉,一起剝皮案震驚了整個(gè)濱河市粟矿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌损拢,老刑警劉巖陌粹,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異福压,居然都是意外死亡掏秩,警方通過查閱死者的電腦和手機(jī)或舞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蒙幻,“玉大人映凳,你說我怎么就攤上這事「松罚” “怎么了魏宽?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵腐泻,是天一觀的道長(zhǎng)决乎。 經(jīng)常有香客問我,道長(zhǎng)派桩,這世上最難降的妖魔是什么构诚? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮铆惑,結(jié)果婚禮上范嘱,老公的妹妹穿的比我還像新娘。我一直安慰自己员魏,他們只是感情好丑蛤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著撕阎,像睡著了一般受裹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上虏束,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天棉饶,我揣著相機(jī)與錄音,去河邊找鬼镇匀。 笑死照藻,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的汗侵。 我是一名探鬼主播幸缕,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼晰韵!你這毒婦竟也來了冀值?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤宫屠,失蹤者是張志新(化名)和其女友劉穎列疗,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浪蹂,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抵栈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年告材,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片古劲。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡斥赋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出产艾,到底是詐尸還是另有隱情疤剑,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布闷堡,位于F島的核電站隘膘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏杠览。R本人自食惡果不足惜弯菊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望踱阿。 院中可真熱鬧管钳,春花似錦、人聲如沸软舌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽佛点。三九已至醇滥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間恋脚,已是汗流浹背腺办。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留糟描,地道東北人怀喉。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像船响,于是被迫代替她去往敵國(guó)和親躬拢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

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