dtcms 模板下载 视频剪辑软件 WebStorm Appuim环境搭建 Eclipse插件 docker安装部署 莱斯分布 database macos redis常用语句 emacs cuda flowjs vue的钩子函数 后台管理界面 react脚手架 网络游戏server编程 oracle行转列函数 excel带格式复制粘贴 linux查询文件内容 python输入输出 python使用教程 javaapplet java入门教程 java数据库 java中的基本数据类型 java结构 jb51 java核心技术 qq免安装版 pdf安装包官方下载 ip切换软件 cdr字体加粗 处理器虚拟化技术 cad自动保存位置 quickchm 360越狱版 倒计时定时器 nginx启动命令 召唤加点90刷图加点
当前位置: 首页 > 学习教程  > 编程语言

springmvc笔记补充——核心技术

2020/11/24 10:01:28 文章标签: 测试文章如有侵权请发送至邮箱809451989@qq.com投诉后文章立即删除

请求转发和重定向 当处理器对请求处理完毕后,向其他资源跳转时,有两种跳转方式:请求转发 与 重定向 。而根据所要跳转的资源类型,又分为两类:跳转到页面与跳转到其他处理器。 注意,对于请求转发的页面&…

请求转发和重定向



当处理器对请求处理完毕后,向其他资源跳转时,有两种跳转方式:请求转发 与 重定向 。而根据所要跳转的资源类型,又分为两类:跳转到页面与跳转到其他处理器。
注意,对于请求转发的页面,可以是 WEB-INF 中的页面;而重定向的页面,是不能为 WEB-INF中的页面。因为重定向相当于用户再次发出一次请求,而用户是不能直接访问 WEB-INF 中资源的。


在这里插入图片描述


springmvc框架把原来的servlet中的请求转发和重定向进行了封装,现在可以使用简单方式实现了。
    
forward:表示转发,实现request.getRequestDispatcher("xx.jsp").forward()
redirect:表示重定向,实现response.sendRedirect("xxx.jsp")

1、forward,请求转发

处理器方法返回 ModelAndView,实现转发 forward操作
语法:setViewName("forward:视图文件完整路径")
forward特点:不和视图解析器一同使用,就当项目中没有视图解析器

对应控制器

@Controller
public class MyController {

    @RequestMapping(value = "/doForward.do")
    public ModelAndView doSome(){
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","-----欢迎使用spring mvc做web开发------" );
        mv.addObject("fun","执行的是doSome方法");

        //=====================重点===========================
        
        //使用视图解析器
        //mv.setViewName("show");
        
        //显式转发
        mv.setViewName("forward:WEB-INF/view/show.jsp");
        
        //=====================重点===========================
        
        return mv;
    }
}

2、redirect 重定向

处理器方法返回ModelAndView,实现转发redirect操作
语法:setViewName("redirect:视图文件完整路径")
redirect特点:不和视图解析器一同使用,就当作项目中没有视图解析器

<br/>

框架对重定向的操作:
1、框架会把model中的简单类型的数据,转为String使用,作为hello.jsp的get请求参数使用
   目的是在 doRedirect.do 和 hello.jsp 两次请求之间传递参数
       
2、在目标hello.jsp可以使用参数集合对象 $(param) 获取请求参数值,格式为:$(param.name)
       
3、重定向不能访问WEB-INF资源

对应控制器

@RequestMapping(value = "/doRedirect.do")
public ModelAndView doWithRedirect(String name,Integer age){
    ModelAndView mv = new ModelAndView();
    //数据放入到 request 作用域
    mv.addObject("name",name);
    mv.addObject("age",age);

     //=====================重点===========================
    
    //重定向
    mv.setViewName("redirect:hello.jsp");
    //http://localhost:8080/08_forward/hello.jsp?name=zhangsan&age=11
    
     //=====================重点===========================
    
    return mv;
}

hello.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>show.jsp</h3><br/>
    <h3>name数据:${name}</h3>
    <h3>age数据:${age}</h3>
</body>
</html>

输入参数如下图

在这里插入图片描述


结果如下图
在这里插入图片描述


虽然网址上传递了参数,但name和age取不到参数,因为重定向是两次请求,参数在第一次请求的作用域里面,无法直接传递到第二个作用域。此时修改hello.jsp,直接访问第一次请求作用域里面的参数。


hello.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>show.jsp</h3><br/>
    <h3>name数据:${param.name}</h3>
    <h3>age数据:${param.age}</h3>
	
    <!--使用request对象中的getParameter方法,可以访问到第一次request作用域-->
    <h3>取参数数据:<%=request.getParameter("name")%></h3>
</body>
</html>

成功取到参数,如下图
在这里插入图片描述


异常处理


springmvc框架采用的是统一,全局的异常处理。把controller中的所有异常处理都集中到一个地方,采用的是aop思想,把业务逻辑和异常处理代码分开。也叫解耦(ou)合。
使用两个注解:1、ExceptionHandler 2、ControllerAdvice


异常处理主要步骤:
    
1	新建一个自定义异常类 MyUserException,再定义它的子类 NameException,AgeException
2	在 controller 抛出 NameException,AgeException
3	创建一个普通类,作为 全局异常处理类
		1>	类上面加上 @ControllerAdvice
		2>	类中方法上面加上 @ExceptionHandler
4	创建对应视图。创建组件扫描器扫描,扫描全局变量处理程序。创建注解驱动。

项目结构如下

在这里插入图片描述


springmvc.xml,加入组件扫描器和注解驱动

<!--处理异常两个步骤-->

<!--1、组件扫描器:扫描全局异常处理程序-->
<context:component-scan base-package="com.zh.handler"/>

<!--2、注解驱动-->
<mvc:annotation-driven/>

MyController.java,控制器方法,向 MyUserException 抛出异常

@Controller
public class MyController {

    @RequestMapping(value = "/some.do")
    public ModelAndView doSome(String name,Integer age) throws MyUserException {
        ModelAndView mv = new ModelAndView();

        //根据请求抛出异常
        if (!"zs".equals(name)){
            throw new NameException("姓名不正确");
        }

        if (age <= 0 || age >= 99){
            throw new AgeException("年龄输入有误");
        }
        
        mv.addObject("name",name);
        mv.addObject("age",age);
        mv.setViewName("show");
        return mv;
    }
}

自定义异常类 MyUserException.java,继承 Exception

public class MyUserException extends Exception{

    public MyUserException() {
        super();
    }
    public MyUserException(String message) {
        super(message);
    }
}

子类 NameException.java

//表示当前用户姓名有异常,抛出NameException
public class NameException extends MyUserException {

    public NameException() {
        super();
    }
    public NameException(String message) {
        super(message);
    }
}

下面创建一个GlobalExceptionHandler.java,作为 全局异常处理类


1、@ControllerAdvice

控制器增强 (可以理解为:增加控制器功能),放在类上面
    
特点:必须让框架知道这个注解所在的包名,需要在springmvc配置文件声明 组件扫描器
指定 @ControllerAdvice 所在的全局异常处理类包名

2、@ExceptionHandler

@ExceptionHandler(异常的class):表示异常的类型,当发生此类型的异常时,由当前方法处理。放在方法上面

处理异常的方法和控制器方法的定义一样,可以有多个参数,可以有ModelAndView,String,void,对象类型的返回值
形参:Exception,表示Controller中抛出的异常对象,通过形参可以获取发送的异常信息

GlobalExceptionHandler.java

//@ControllerAdvice 增强控制器
@ControllerAdvice
public class GlobalExceptionHandler {
	
    //处理NameException异常
    @ExceptionHandler(value = NameException.class)
    public ModelAndView doNameException(Exception exception){

        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","用户名必须是zs,其他用户不能访问");
        mv.addObject("ex",exception);
        //指定视图
        mv.setViewName("nameError");
        return mv;
    }

    //处理AgeException异常
    @ExceptionHandler(value = AgeException.class)
    public ModelAndView doAgeException(Exception exception){
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","年龄输入范围有误");
        mv.addObject("ex",exception);
        mv.setViewName("ageError");
        return mv;

    }

    //处理NameException,AgeException以外的,不知类型的异常
    @ExceptionHandler
    public ModelAndView doOtherException(Exception exception){
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","其他不知类型的异常");
        //指定视图
        mv.setViewName("defaultError");
        return mv;
    }
}

检测姓名异常
在这里插入图片描述


结果如下
在这里插入图片描述


检测未知异常
在这里插入图片描述


结果如下
在这里插入图片描述


拦截器


拦截器说明:

1	拦截器是springmvc中的一种,需要实现HandlerInterceptor接口
2	拦截器和过滤器类似,功能方向侧重点不同。过滤器是用来过滤请求参数,设置编码字符集等。
	拦截器是拦截用户的请求,可以对多个Controller做拦截。
3	拦截器是全局的,可以对多个Controller做拦截。
	一个项目中可以有0个或多个拦截器,他们在一起拦截用户的请求。
	拦截器常用在:用户登录处理,权限检查,记录日志。

拦截器的使用步骤:

1	定义普通类实现HandlerInterceptor接口,实现接口的三个方法
2	在springmvc文件中,声明拦截器,指定拦截请求的uri地址

拦截器的执行时间:

1	在请求处理之前,也就是controller类中方法执行之前先被拦截
2	在控制器方法执行之后也会执行拦截器
3	在请求处理完成后也会执行拦截器

在主配置文件sprinmvc.xml中,声明拦截器

<!--声明拦截器:拦截器可以有0个或者多个-->
<mvc:interceptors>

    <!--声明一个拦截器-->
    <mvc:interceptor>
        <!--
        指定拦截请求的uri地址
            path:就是uri地址,可以使用通配符 **
              **:表示任意字符,文件或者多级目录中的文件
        -->
        <mvc:mapping path="/**"/>
        <!--声明拦截器对象-->
        <bean class="com.zh.handler.MyInterceptor"/>
    </mvc:interceptor>
    
</mvc:interceptors>

创建一个MyInterceptor.java,作为拦截器类,继承自HandlerInterceptor,实现三个方法:preHandle,postHandle,afterCompletion


在这里插入图片描述


preHandle:预处理方法(重要)

预处理方法:preHandle
     
重要:是整个项目的入口,门户
当preHandle返回true,请求可以被处理
当preHandle返回false,请求到此方法就截止

参数:Object handler:被拦截的控制器对象
返回值:boolean

true:请求通过拦截器验证,可以处理拦截器方法
    
  控制台显示结果:
      MyInterceptor拦截器的preHandle()方法执行了!
      MyController控制器的doSome()方法执行!
      MyInterceptor拦截器的postHandle()方法执行了!
      MyInterceptor拦截器的afterCompletion()方法执行了!

false:请求没有通过拦截器的验证,请求到达拦截器就截止了。请求没有被处理
    
  控制台显示结果:
      MyInterceptor拦截器的preHandle()方法执行了!

特点:
  1、该方法在控制器方法(MyController的doSome)之前执行,用户请求首先到达该方法
  2、在该方法中可以获取请求的信息,验证请求是否符合要求。可以验证用户是否登录,验证用户是否有权访问某个连接地址(url),
     如果验证失败,可以截断请求;如果验证成功,可以放行请求,此时控制器方法才能执行


MyInterceptor.java

//拦截器类:看作是多个控制器中公用的功能,集中到拦截器统一处理,使用的是aop思想(面向切面编程)。
public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor拦截器的preHandle()方法执行了!");
        return true;
    }

   /*
    * 后处理方法:postHandle
    * 参数:
    * Object handler:被拦截的处理器对象MyController
    * ModelAndView mv:处理器方法的返回值
    *
    * 特点:
    *   1、在处理器方法(MyController.doSome)之后执行
    *   2、能够获取到处理器方法的返回值ModelAndView,可以修改ModelAndView中的数据和视图,会影响到最后的输出结果
    *   3、主要是对原来的执行结果做第二次修正
    * */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mv) throws Exception {
        System.out.println("MyInterceptor拦截器的postHandle()方法执行了!");
    }

   /*
    * 最后执行方法:afterCompletion
    * 参数:
    *   Object handler:被拦截的处理器对象
    *   Exception ex:程序中发生的异常
    * 特点:
    *   1、在请求处理完成后执行。框架中规定是你的视图处理完成后,对视图执行了forward。就认为请求处理完成。
    *   2、一般做资源回收,程序请求中创建的一些对象,在这里删除,回收占用的内存
    *
    * */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor拦截器的afterCompletion()方法执行了!");
    }
}

多个拦截器时

在框架中保存多个拦截器是ArrayList,
按照声明的先后顺序放入ArrayList

在这里插入图片描述


第一个拦截器preHandle=true,第二个拦截器preHandle=true


第一个拦截器类

public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("11111--MyInterceptor拦截器的preHandle()方法执行了!");
        return true;
    }
        @Override
    public void postHandle(......){
         System.out.println("11111--MyInterceptor拦截器的postHandle()方法执行了!");
    }
        .....

第二个拦截器类

public class MyInterceptor2 implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("22222--MyInterceptor拦截器的preHandle()方法执行了!");
        return true;
    }
        @Override
    public void postHandle(......){
         System.out.println("22222--MyInterceptor拦截器的postHandle()方法执行了!");
    }
        .....

配置文件中也要同时声明两个拦截器

    <mvc:interceptors>

        <!--声明一个拦截器-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.zh.handler.MyInterceptor"/>
        </mvc:interceptor>
        
        <!--声明第二个拦截器-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.zh.handler.MyInterceptor2"/>
        </mvc:interceptor>

    </mvc:interceptors>


运行结果如下

11111--MyInterceptor拦截器的preHandle()方法执行了!
22222--MyInterceptor拦截器的preHandle()方法执行了!
MyController控制器的doSome()方法执行!
22222--MyInterceptor拦截器的postHandle()方法执行了!
11111--MyInterceptor拦截器的postHandle()方法执行了!
22222--MyInterceptor拦截器的afterCompletion()方法执行了!
11111--MyInterceptor拦截器的afterCompletion()方法执行了!

第一个拦截器preHandle=true,第二个拦截器preHandle=false

执行结果为

11111--MyInterceptor拦截器的preHandle()方法执行了!
22222--MyInterceptor拦截器的preHandle()方法执行了!
11111--MyInterceptor拦截器的afterCompletion()方法执行了!

第一个拦截器preHandle=false,第二个拦截器preHandle=true

11111--MyInterceptor拦截器的preHandle()方法执行了!

拦截器和过滤器的区别,了解


1	过滤器是servlet中的对象,拦截器是框架中的对象
2	过滤器实现Filter接口,拦截器实现HandlerInterceptor
3	过滤器是用来设置request,response的参数,属性,侧重对数据过滤的
	拦截器用来验证请求,能截断请求
	
4	过滤器是在拦截器之前先执行
5	过滤器是tomcat服务器创建的对象
	拦截器是springmvc容器中创建的对象

6	过滤器是一个执行时间点
	拦截器是三个执行时间点

7	过滤器可以处理jsp,js,html等
	拦截器是侧重拦截对Controller的对象。如果你的请求不能被DispatcherServlet接收,这个请求	不会执行拦截器内容
	
8	拦截器拦截普通类方法执行,过滤器过滤servlet请求响应

本文链接: http://www.dtmao.cc/news_show_400204.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?