SpringMVC第三談(請求重定向和轉發、異常處理、攔截器、SSM的整合)

在這裏插入圖片描述

本人是一名物聯網工程專業大二的學生,是互聯網浪潮中一朵小小的浪花,寫博客即是爲了記錄自己的學習歷程,又希望能夠幫助到很多和自己一樣處於起步階段的萌新。臨淵羨魚,不如退而結網。一起加油!
博客主頁:https://blog.csdn.net/qq_44895397

SpringMVC完整般思維導圖

請求重定向和轉發

當處理器對請求處理完畢後,向其它資源進行跳轉時,有兩種跳轉方式:請求轉發與重定向。而根據所要跳轉的資源類型,又可分爲兩類:跳轉到頁面與跳轉到其它處理器。
對於請求轉發的頁面,可以是WEB-INF中頁面;而重定向的頁面,是不能爲WEB-INF中頁的。因爲重定向相當於用戶再次發出一次請求,而用戶是不能直接訪問 WEB-INF 中資源的
center
SpringMVC 框架把原來 Servlet 中的請求轉發和重定向操作進行了封裝。現在可以使用簡單的方式實現轉發和重定向。

  • forward:表示轉發,實現request.getRequestDispatcher(“xx.jsp”).forward()
  • redirect:表示重定向,實現 response.sendRedirect(“xxx.jsp”)

請求轉發

處理器方法返回 ModelAndView 時,需在 setViewName()指定的視圖前添加 forward:,且此時的視圖不再與視圖解析器一同工作,這樣可以在配置瞭解析器時指定不同位置的視圖。視圖頁面必須寫出相對於項目根的路徑。forward 操作不需要視圖解析器。處理器方法返回 String,在視圖路徑前面加入 forward: 視圖完整路徑。
語法:setViewName(“forward:使徒的完整路徑”);
在這裏插入圖片描述

@RequestMapping("/handlerIntercwptor.do")
public ModelAndView forwardDemo(String name ,Integer age){
    ModelAndView mv = new ModelAndView();
    mv.addObject("myname",name);
    mv.addObject("myage",age);
    mv.setViewName("forward:/WEB-INF/view/forward.jsp");
    return mv;
}

請求重定向

在處理器方法返回的視圖字符串的前面添加 redirect:,則可實現重定向跳轉。
處理器方法定義:
在這裏插入圖片描述

@RequestMapping("/handlerIntercwptor.do")
public ModelAndView redirectDemo(String name ,Integer age){
    ModelAndView mv = new ModelAndView();
    mv.addObject("myname",name);
    mv.addObject("myage",age);
    mv.setViewName("redirect:/redirect.jsp");
    //mv.setViewName("redirect:/WEB-INF/view/forward.jsp");
    return mv;
}

異常處理

@ExceptionHandler 註解

使用註解@ExceptionHandler 可以將一個方法指定爲異常處理方法。該註解只有一個可選屬性 value,爲一個 Class<?>數組,用於指定該註解的方法所要處理的異常類,即所要匹配的異常。

而被註解的方法,其返回值可以是 ModelAndView、String,或 void,方法名隨意,方法參數可以是 Exception 及其子類對象、HttpServletRequest、HttpServletResponse 等。系統會自動爲這些方法參數賦值。

對於異常處理註解的用法,也可以直接將異常處理方法註解於Controller 之中
在這裏插入圖片描述

public @interface ExceptionHandler {
    Class<? extends Throwable>[] value() default {};
}

使用步驟:

  1. 自定義異常類
  2. 修改Controller拋出異常
  3. 自定義異常響應頁面
  4. 自定義一場全局處理類
  5. 修改配置文件(聲明異常類的存在)
    在這裏插入圖片描述

Controller拋出異常:

@RequestMapping("/some.do")
public ModelAndView addStudent(String name, Integer age) throws MyException {
    ModelAndView mv = new ModelAndView();
    if (!"zs".equals(name)) {
        throw  new NameException("名字有誤");
    }
    if(age==null||age>100){
        throw new AgeException("年齡異常");
    }
    mv.addObject("myname", name);
    mv.addObject("myage", age);
    mv.setViewName("show");
    return mv;
}

在這裏插入圖片描述

/**
 * @ControllerAdvice :控制器增強,給控制器類增強功能
 * 在類上使用
 * 需要使用組件掃描器,讓框架知道這個註解所在的包名
 *
 * 處理異常的方法和控制器方法的定義一樣可以以有多個參數,可以返回ModelAndView
 * String,void對象返回值
 * 形參:Exception,獲取異常發生的信息
 *  @ExceptionHandler :異常的class,表示發生異常的類型
 */
@ControllerAdvice
public class MyHandler {

    @ExceptionHandler(NameException.class)
    public ModelAndView ageExcrption(Exception e){
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","寧輸入的姓名異常");
        mv.addObject("message",e.getMessage());
        mv.setViewName("ageErorr");
        return mv;
    }
}

在這裏插入圖片描述

攔截器

SpringMVC 中的 Interceptor 攔截器它的主要作用是攔截指定的用戶請求,並進行相應的預處理後處理。其攔截的時間點在“處理器映射器根據用戶提交的請求映射出了所要執行的處理器類,並且也找到了要執行該處理器類的處理器適配器,在處理器適配器執行處理器之前”。當然,在處理器映射器映射出所要執行的處理器類時,已經將攔截器與處理器組合爲了一個處理器執行鏈,並返回給了中央調度器。

一個攔截器的執行

在這裏插入圖片描述

  1. preHandle(request,response, Object handler):

該方法在處理器方法執行之前執行。其返回值爲 boolean,若爲 true,則緊接着會執行處理器方法,且會將 afterCompletion()方法放入到一個專門的方法棧中等待執行。
在這裏插入圖片描述

/**
 *  preHandle:預處理方法,
 *  Object handler:被攔截的控制器對象
 *  返回值:boolean
 *      true:表示能夠進入控制方法,
 *      false:請求被攔截
 *  特點:
 *      1、方法在控制器方法之前執行
 *      2、這個方法中能夠驗證請求的信息,驗證請求是否符合要求
 *          驗證失敗可以截斷請求
 */
@Override
public boolean preHandle(HttpServletRequest request,
                         HttpServletResponse response,
                         Object handler) throws Exception {
    System.out.println("preHandle,驗證通過");
    return true;
}
  1. postHandle(request,response,Objecthandler,modelAndView):

該方法在處理器方法執行之後執行。處理器方法若最終未被執行,則該方法不會執行。由於該方法是在處理器方法執行完後執行,且該方法參數中包含 ModelAndView,所以該方法可以修改處理器方法的處理結果數據,且可以修改跳轉方向。

在這裏插入圖片描述

 /**
     *後處理方法:
     * handler :被攔截的處理器對象
     * modelAndView:處理器方法的返回值,能夠修改
     * 在處理器方法之後進行,沒有返回值
     * 能夠獲取處理器返回值,能夠修改視圖和值
     * 對執行結果進行二次修正
     */
    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler,
                           ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
    }
  1. afterCompletion(request,response, Object handler, Exception ex):

當 preHandle()方法返回 true 時,會將該方法放到專門的方法棧中,等到對請求進行響應的所有工作完成之後才執行該方法。即該方法是在中央調度器渲染(數據填充)了響應頁面之後執行的,此時對 ModelAndView 再操作也對響應無濟於事。
afterCompletion 最後執行的方法,清除資源,例如在 Controller 方法中加入數據
在這裏插入圖片描述

/**
 * 最後執行的方法
 *
 *Exception:程序發生的異常
 * 在請求處理完成過後執行,視圖處理完成後,對視圖進行了forward就認爲請求處理完成
 * 一般做資源回收工作
 */
@Override
public void afterCompletion(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler,
                            Exception ex) throws Exception {
    System.out.println("afterCompletion");
}

攔截器中方法與處理器方法的執行順序如下圖:
在這裏插入圖片描述
在這裏插入圖片描述

多個攔截器的執行

當有多個攔截器時,形成攔截器鏈。攔截器鏈的執行順序,與其註冊順序一致。需要再次強調一點的是,當某一個攔截器的preHandle()方法返回 true 並被執行到時,會向一個專門的方法棧中放入該攔截器的 afterCompletion()方法。
在這裏插入圖片描述

SSM的整合

兩個容器:

  1. SpringMVC容器,管理Controller對象
  2. Spring容器,管理service,dao,工具類

實現步驟:

  1. 建表

  2. 新建maven項目

  3. 加入依賴:
    SpringMVC,servlet,jsp,jackson,Spring,Spring事務,Spring-MyBatis,Mybatis,mysql驅動,druid連接池

  4. web.xml
    1)註冊DispatcherServlet,目的:創建springmvc容器,才能創建Controller類對象
    2)註冊spring監聽器:ContextLoaderListener,創建spring容器對象,才能創建service,dao等對象
    3)註冊字符集過濾器,post請求亂碼

  5. 創建包,Controller,service,dao,實體類

  6. springmvc,spring,mybatis的配置文件

pom.xml:

<dependencies>
    <!--添加依賴-->
    <!--servlet依賴-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <!-- jsp依賴 -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2.1-b03</version>
        <scope>provided</scope>
    </dependency>
    <!--springmvc的依賴,自動導入了spring的依賴-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.5.RELEASE</version>
    </dependency>
    <!--spring管理事務的依賴-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>5.2.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.2.5.RELEASE</version>
    </dependency>
    <!--jkson的依賴-->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.9.0</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.0</version>
    </dependency>
    <!--mybatis的依賴,spring-mybatis的依賴,德魯伊連接池-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.1</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.1</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.9</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.12</version>
    </dependency>
    <!--Resource註解無法使用-->
    <dependency>
        <groupId>javax.annotation</groupId>
        <artifactId>javax.annotation-api</artifactId>
        <version>1.3.1</version>
    </dependency>
</dependencies>

spring的主配置文件:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:conf/mybatis.xml" />
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
        <property name="basePackage" value="com.yky.dao" />
    </bean>

    <!--創建出service的對象使用註解完成,添加註解掃描器-->
    <context:component-scan base-package="com.yky.service" />

springmvc的配置文件:

  1. 組件掃描器
  2. 視圖解析器
  3. 數據類型轉爲json時用到@ResponseBody註解啓動
    能夠解決訪問靜態資源時的衝突問題
<context:component-scan base-package="com.yky.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/>

本站所有文章均爲原創,歡迎轉載,請註明文章出處:愛敲代碼的小遊子

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章