SpringMVC_04_转发重定向and全局异常处理and拦截器

四、SpringMVC核心技术

4.1 请求重定向

SpringMVC框架把原来Servlet表中的请求转发和重定向操作进行了封装,现在可以可以使用简单的方式实现转发和重定向

forward:表示转发,实现request.getRequestDispatcher("xx.jsp").forward(request,response);,转发在服务器内部进行操作,一次请求

redirect:表示重定向,实现response.sendRedirect("xxx.jsp"),用户地址栏变化,二次请求,由于是用户发起,不能访问WEB-INF下的内容

请求

格式:

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

使用封装的请求转发,可以不通过视图解析器,这里路径名使用的是全路径名

转发的显示页面可以自定义

案例:

请求页面:

<p>SpringMVC封装的请求转发</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");

实现重定向的步骤:

  1. 发出请求的前端资源
    <p>SpringMVC封装的请求重定向</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. 后端控制器接收请求,添加数据,请求重定向
    @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>
    
    得到的数据: <br>
    name: ${name} <br>
    age: ${age} <br>
    
    </body>
    </html>
  1. 显示效果:
image-20211019160139366.png
  1. 分析:

    • 请求重定向后页面地址栏发生变化

    • 加入的数据没有得到

    • 在地址栏中发现数据出现在地址栏的请求参数上

  2. 结论:

    请求重定向是两次请求,request域中无法得到上一个request的数据,重定向的页面地址栏会变化,加入的数据作为请求参数出现

  3. 得到数据的解决方案

    显示页面中将el表达式默认request域改为从param参数中农获取

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

${param.name}相当于

    数据相当于:<%=request.getParameter("name")%>
  1. 当我们要访问WEB-INF下的数据,会发生404

    重定向不能访问受保护资源

框架对重定向的操作:

  1. 框架会把Model中的简单类型数据,转为string使用,作为hello.jsp的get请求参数使用

    目的:在doRedirect.do 和 hello.jsp两次请求之间可以传递数据

  2. 在目标hello.jsp页面可以使用参数集合对象{param}获取请求参数值,例如:{param.myname}

注意:

关键:SpringMVC的请求转发和请求重定向不和视图解析器一起使用


4.2 异常处理

业务功能和异常处理进行解耦合,使用的aop思想,SpringMVC框架采用的是统一全局异常处理方案,把Controller中的所有异常处理都集中到一个地方。采用的是aop的思想,把业务逻辑和异常处理代码分开。

使用两个注解:

  1. @ExceptionHandler

  2. @ControllerAdvice

异常处理步骤:

  1. 新建Maven web项目

  2. 加入依赖

  3. 新建一个自定义异常类 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. 创建一个普通类,作用全局异常处理类

    1. 在类上面加入@ControllerAdvice

    2. 在类中定义方法,方法上面加入@ExceptionHandler

    //@ControllerAdvice 注解表示控制器通知 / 增强
    @ControllerAdvice
    public class GlobalExceptionHandler {
    
    //    @ExceptionHandler 注解映射解决具体异常的方法
     // 有一个参数 就是要解决异常的class类
     // 形参Exception,表示Controller中跑出的异常对象,通过形参可以获取发生的异常信息
     // 方法返回值和对应的切入点的返回值一样
     @ExceptionHandler(value = NameException.class)
     public ModelAndView doNameException(Exception ex){
     // 处理Name异常
     /*
     异常处理逻辑:
     1\. 需要把异常记录下来,记录到数据库,日志文件
     记录日志发生的时间,哪个方法发生的,异常错误内容
     2\. 发送通知,把异常信息通过邮件 / 短信 / 微信发生给相关人员
     3\. 给用户友好的提示
     */
     ModelAndView mv = new ModelAndView();
     mv.addObject("msg","姓名不准确");
     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;
     }
    }

当我们的异常不是name和age产生,即其他异常就会映射到不加value的@ExceptionHandler注解下的方法来处理

  1. 创建处理异常的视图页面

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>
    系统提示:${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>
    系统提示:${ex.message}
    </body>
    </html>
  1. 创建SpringMVC的配置文件

    1. 组件扫描器,扫描@Controller注解

    2. 组件扫描器,扫描@ControllerAdvice所在的包名

    3. 声明注解驱动

    <?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 />
     <context:component-scan base-package="com.GeekRose.handler" />
    </beans>

这里命名空间记得导入正确

  1. 效果:

当我们输入错误数据 例如 姓名为zhangsan时

image-20211019180147911.png

得到的处理结果为:

image-20211019180204417.png

使用全局异常处理,主要是为了实现解耦合,不用自己不断写try catch,异常处理代码和业务逻辑代码实现分离


4.3 拦截器

SpringMVC中的Interceptor拦截器是非常重要和相当有用的,它的主要作用是拦截指定的用户请求,并进行相应的预处理和后处理。其拦截的时间点在“处理器映射器根据用户提交的请求映射出了所要执行的处理器类,并且也找到了要执行该处理器类的处理器适配器,在处理器适配器执行处理器之前”。当然,在处理器映射器映射出所要执行的处理器类时,已经将拦截器与处理器组合为了一个处理器执行链,并返回给了中央调度器。

实现了HandlerInterceptor接口的都是拦截器

拦截器和过滤器类似,但是侧重点不同 功能方向不同。

  • 过滤器用来过滤请求参数,设置编码字符集等工作。

  • 拦截器是拦截用户的请求,对请求做判断处理的。

  • 拦截器是全局的,可以对多个Controller做拦截。

    一个项目可以有0个或多个拦截器,他们在一起拦截用户的请求。

    拦截器常用在用户登录处理和权限检查记录日志。

拦截器的使用步骤:

  1. 定义类实现HandlerInerterceptor接口

  2. 在SpringMVC配置文件中声明拦截器,让框架知道拦截器的存在

拦截器的执行时间:

  1. 在请求处理之前,也就是controller类中的方法执行之前先被拦截

  2. 在控制器方法执行之后也会执行拦截器

  3. 在请求处理完成后也会执行拦截器

预处理方法
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 return false;
}

返回值:布尔值

  • true

  • false

方法参数:

  • HttpServletRequest 请求

  • HttpServletResponse 响应

  • Object Handler 处理器对象(MyController对象)

预处理方法在执行处理器方法前执行(MyController.doSome),一般用作请求判断,验证请求是否符合要求。可以验证用户是否登录,验证用户是否有权限访问某个连接地址(URL)

如果验证失败,可以截断请求,请求不能被处理

如果验证成功,可以方形请求,此时控制器方法才能执行

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

}

返回值:void

方法参数:

  • HttpServletRequest 请求

  • HttpServletResponse 响应

  • Object handler 处理器对象

  • ModelAndView modelAndView 数据与视图对象

后处理方法在处理器方法(MyController.doSome)执行后执行,一般用作数据的二次修订

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

}

返回值:void

请求参数:

  • HttpServletRequest 请求

  • HttpServletResponse 响应

  • Object handler 处理器对象

  • Exception ex 异常对象

最后执行的方法在请求完成后执行(当请求进行forward,发送到视图时被认定为请求完成),一般用作资源回收处理,程序中创建的一些对象在这里进行删除,释放占用的内存

配置文件声明拦截器

拦截器的声明

<!--    声明拦截器-->
 <mvc:interceptors>
 <mvc:interceptor>
<!--            映射地址 /** 表示工程目录下的所有请求都会被拦截
 /user/** 表示user下的所有请求都会被拦截
-->
 <mvc:mapping path="/user/**"/>
 <bean class="com.GeekRose.interceptor.MyInterceptor" />
 </mvc:interceptor>
 </mvc:interceptors>

拦截器:看做多个Controller中公用的功能,集中到拦截器统一处理,使用的aop思想

拦截器图解:

image-20211020131724028.png
多个拦截器

多个拦截器的执行顺序

拦截器的执行顺序为拦截器的声明顺序

图解:

image-20211020133227066.png

当我们定义两个拦截器:

拦截器定义:

拦截器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>
<!--            映射地址 /** 表示工程目录下的所有请求都会被拦截
 /user/** 表示user下的所有请求都会被拦截
-->
 <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>

两个拦截器的预处理方法都为true

控制台输出:

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

多个拦截器执行链:

image-20211020134206876.png

当拦截器1的预处理方法为true,拦截器2的预处理为false

处理结果:

MyInterceptor1-preHandle
MyInterceptor2-preHandle
MyInterceptor1-afterCompletion

拦截器1预处理为true,进入拦截器2的预处理为false,此时无法进行执行,截断请求。因为拦截器1的预处理为true,所以拦截器1的最终执行方法会执行。

当拦截器1的预处理为false,拦截器2的预处理为true

处理结果:

MyInterceptor1-preHandle

直接截断请求,不会到拦截器2

只要有一个拦截器为false,请求到此结束不会到控制器中

拦截器和过滤器的区别
  1. 过滤器是Servlet规范中的对象,拦截器是框架中的对象

  2. 过滤器实现Filter接口的对象,拦截器是实现HandlerInterceptor接口

  3. 过滤器用来设置request,response的参数,属性的,侧重对数据过滤的,拦截器是用来验证请求的,能截断请求。

  4. 过滤器是在拦截器之前先执行的

  5. 过滤器是tomcat服务器创建的对象,拦截器是SpringMVC容器中创建的对象

  6. 过滤器是一个执行时间点

    拦截器有三个执行时间点

  7. 过滤器可以处理jsp、js、html等

    拦截器是侧重拦截对Controller的请求,如果你的请求不能被中央调度器接收,这个请求不会执行拦截器内容

  8. 拦截器拦截普通方法执行,过滤器过滤Servlet请求响应

拦截器权限登录案例

实现步骤:

  1. 新建maven项目

  2. 修改web.xml注册中央调度器

  3. 新进index.jsp发起请求

  4. 创建MyController处理请求

  5. 创建结果show.jsp

  6. 创建一个login.jsp,模拟登录(把用户信息放入session中)创建一个logout.jsp,模拟退出系统(从session中删除数据)

  7. 创建拦截器,从session中获取用户的登录数据,验证能否访问系统

  8. 创建一个验证的jsp,如果验证失败,给出提示

  9. 创建springmvc配置文件

    声明组件扫描器

    声明拦截器

实现效果:

当我们没有登录权限(session没有数据时),会被拦截器阶段请求调到提示页面,当我们有登录权限,就会访问到数据

这里登录登出在jsp中实现

代码实现:

发出请求的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>登录验证</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>

获取登录权限 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>

登出删除权限 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>
你的请求已经被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>
<!--            映射地址 /** 表示工程目录下的所有请求都会被拦截
 /user/** 表示user下的所有请求都会被拦截
-->
 <mvc:mapping path="/user/**"/>
 <bean class="com.GeekRose.interceptor.MyInterceptor1" />
 </mvc:interceptor>
 </mvc:interceptors>

</beans>

效果展示:

image-20211021122827187.png

没有登录权限:提交后

image-20211021122848132.png

获取权限:

image-20211021122914131.png

此时我们再进行提交

image-20211021122930101.png

结果:

image-20211021122941710.png

当我们删除权限登出

image-20211021123005857.png

我们再提交数据

结果:

image-20211021123030607.png

4.4 SpringMVC的内部处理流程

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

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

SpringMVC接收请求到处理完成的过程

  1. 用户发起请求some.do

  2. DispatcherServlet接收请求some.do,把请求转交给处理器映射器,

    处理器映射器是SpringMVC框架的一种对象,框架把实现了HandlerMapping接口的类都叫映射器

    处理器映射器作用:根据请求,从SpringMVC容器对象中获取处理器对象(MyController controller = ctx.getBean("some.do"))

    框架把找到的处理器对象放到一个叫做处理器执行链的类保存(HandlerExecutionChain)

    HandlerExectutionChain:类中保存着

    • 处理器对象(MyController)

    • 项目中所有的拦截器(List<HandlerInterceptor> interceptorList)

  3. DispatcherServlet把HandlerExecutionChain中的处理器对象交给了处理器适配器对象(多个)

    处理器适配器是框架中的一种对象,是SpringMVC框架中的对象,需要实现HandlerAdapter接口

    处理器适配器作用:执行处理器方法(调用MyController.doSome() 得到返回值ModelAndView)

    得到的结果再通过处理器适配器返回给中央调度器

  4. DispatcherServlet把3中获取的ModelAndView交给视图解析器对象

    视图解析器:SpringMVC中的对象,需要实现ViewResolver接口(可以有多个)

    视图解析器作用:组成视图完整路径,使用前缀、后缀,并创建View对象。view是一个接口,表示视图的,在框架中jsp、html不是string字符串表示,而是使用view和它的实现类表示视图

    InternalResourceView:视图类,表示jsp文件,视图解析器会创建InternalResourceView类对象,这个对象里面,有一个属性url=/WEB-INF/view/show.jsp

  5. DispathcerServlet把4步骤中创建的View对象获取到,调用View类自己的方法,把Model数据放入到request作用域,执行对象视图的forward。请求结束

执行流程图解:

image-20211021130748705.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 193,968评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,682评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,254评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,074评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,964评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,055评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,484评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,170评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,433评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,512评论 2 308
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,296评论 1 325
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,184评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,545评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,150评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,437评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,630评论 2 335

推荐阅读更多精彩内容