springmvc

springmvc,第1张

springmvc

本文来自动力节点springmvc,方便复习使用

文章目录

SpringMVC 概述

SpringMVC 简介第一个注解的 SpringMVC 程序使用 SpringMVC 框架 web 请求处理顺序SpringMVC 的 MVC 组件SpringMVC 执行流程(理解)

流程图:执行流程简单分析 第2章 SpringMVC 注解式开发

@RequestMapping 定义请求规则

指定模块名称对请求提交方式的定义 处理器方法的参数

逐个参数接收请求参数中文乱码问题校正请求参数名@RequestParam对象参数接收对象参数接收 处理器方法的返回值

返回 ModelAndView返回 String返回 void(了解)返回对象 Object返回 List 集合返回字符串对象 静态资源访问

配置详解静态资源访问 地址的相关问题

地址分类 SSM 整合开发

搭建 SSM 开发环境

maven pom.xml配置 web.xml定义包,组织程序的结构。编写配置文件实体类dao接口和映射文件service接口和实现类处理器定义首页文件 index.jsp注册学生页面 --- addStudent.jsp浏览学生页面 --- listStudent.jsp SpringMVC 核心技术

请求重定向和转发

请求转发请求重定向 异常处理

@ExceptionHandler 注解 拦截器

一个拦截器的执行多个拦截器的执行拦截器和过滤器的区别权限拦截器举例

SpringMVC 概述 SpringMVC 简介

SpringMVC:是基于spring的一个框架, 实际上就是spring的一个模块, 专门是做web开发的。 理解为servlet的一个升级

web开发底层是servlet , 框架是在servlet基础上面加入一些功能,让你做web开发方便。SpringMVC就是一个Spring。 Spring是容器,ioc能够管理对象。SpringMVC能够创建对象, 放入到容器中(SpringMVC容器), springmvc容器中放的是控制器对象,我们要做的是 使用@Contorller创建控制器对象, 把对象放入到springmvc容器中, 把创建的对象作为控制器使用
这个控制器对象能接收用户的请求, 显示处理结果,就当做是一个servlet使用。使用@Controller注解创建的是一个普通类的对象, 不是Servlet。 springmvc赋予了控制器对象一些额外的功能。

web开发底层是servlet, springmvc中有一个对象是Servlet : DispatherServlet(中央调度器),它负责接收用户的所有请求, 用户把请求给了DispatherServlet, 之后DispatherServlet把请求转发给 我们的Controller对象, 最后是Controller对象处理请求。

第一个注解的 SpringMVC 程序

    新建web项目,骨架 webapp,web.xml文件的版本记得要改!

    pom.xml

    在创建好 web 项目后,加入 Servlet 依赖,SpringMVC 依赖

    
        javax.servlet
        javax.servlet-api
        3.1.0
        provided
    
    
        org.springframework
        spring-webmvc
        5.2.5.RELEASE
    
    
    

    web.xml(较为固定的写法)

     
        
            myweb
            org.springframework.web.servlet.DispatcherServlet
    
            
            
                
                contextConfigLocation
                
                classpath:springmvc.xml
            
    
            
            1
        
    
        
            myweb
            
            *.do
        
    

    index.jsp show.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
        Title
    
    
         

    第一个springmvc项目

    发起some.do的请求

    发起other.do的请求

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
        Title
    
    
        /WEB-INF/view/show.jsp从request作用域获取数据
    msg数据:${msg}
    fun数据:${fun}

    controller

    package ysk.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    
    @Controller
    public class MyController {
        
    
        
        @RequestMapping(value = "/some.do")
         //@RequestMapping(value = {"/some.do","/first.do"})
        public ModelAndView doSome(){
            ModelAndView mv = new ModelAndView();
            mv.addObject("msg","欢迎使用springmvc做web开发");
            mv.addObject("fun","执行的是doSome方法");
            mv.setViewName("/show.jsp");
            return mv;
        }
    }
    

    修改视图解析器的注册

SpringMVC 框架为了避免对于请求资源路径与扩展名上的冗余,在视图解析器 InternalResouceViewResolver 中引入了请求的前辍与后辍。而 ModelAndView 中只需给出要跳 转页面的文件名即可,对于具体的文件路径与文件扩展名,视图解析器会自动完成拼接。


    
    
    
    

把 show.jsp 文件放到 /WEB-INF/jsp/路径中

    修改处理器

    //指定视图, 指定视图的完整路径
    //框架对视图执行的forward *** 作, request.getRequestDispather("/show.jsp).forward(...)
    //mv.setViewName("/show.jsp");
    //mv.setViewName("/WEB-INF/view/show.jsp");
    //mv.setViewName("/WEB-INF/view/other.jsp");
    
    
    //当配置了视图解析器后,可以使用逻辑名称(文件名),指定视图
    //框架会使用视图解析器的前缀 + 逻辑名称 + 后缀 组成完成路径, 这里就是字符连接 *** 作
    ///WEB-INF/view/ + show + .jsp
    mv.setViewName("show");
    
使用 SpringMVC 框架 web 请求处理顺序

SpringMVC 的 MVC 组件

SpringMVC 执行流程(理解) 流程图:

执行流程简单分析
(1)浏览器提交请求到中央调度器
(2)中央调度器直接将请求转给处理器映射器。
(3)处理器映射器会根据请求,找到处理该请求的处理器,并将其封装为处理器执行链后返回给中央调度器。
(4)中央调度器根据处理器执行链中的处理器,找到能够执行该处理器的处理器适配器。
(5)处理器适配器调用执行处理器。
(6)处理器将处理结果及要跳转的视图封装到一个对象 ModelAndView 中,并将其返回给处理器适配器。
(7)处理器适配器直接将结果返回给中央调度器。
(8)中央调度器调用视图解析器,将 ModelAndView 中的视图名称封装为视图对象。
(9)视图解析器将封装了的视图对象返回给中央调度器
(10)中央调度器调用视图对象,让其自己进行渲染,即进行数据填充,形成响应对象。
(11)中央调度器响应浏览器。

处理映射器的作用:根据请求,从springmvc容器对象中获取处理器对象

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

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

第2章 SpringMVC 注解式开发 @RequestMapping 定义请求规则 指定模块名称

通过@RequestMapping 注解可以定义处理器对于请求的映射规则。该注解可以注解在方 法上,也可以注解在类上,但意义是不同的。value 属性值常以“/”开始。

@RequestMapping 的 value 属性用于定义所匹配请求的 URI。但对于注解在方法上与类 上,其 value 属性所指定的 URI,意义是不同的。

一个@Controller 所注解的类中,可以定义多个处理器方法。当然,不同的处理器方法 所匹配的 URI 是不同的。这些不同的 URI 被指定在注解于方法之上的@RequestMapping 的 value 属性中。但若这些请求具有相同的 URI 部分,则这些相同的 URI,可以被抽取到注解在类之上的@RequestMapping 的 value 属性中。此时的这个 URI 表示模块的名称。URI 的请求 是相对于 Web 的根目录。

想象成 提取公因式!

@Controller
@RequestMapping("/test")
public class MyController { 

index.jsp:

 

发起some.do的请求

对请求提交方式的定义

对于@RequestMapping,其有一个属性 method,用于对被注解方法所处理请求的提交 方式进行限制,即只有满足该 method 属性指定的提交方式的请求,才会执行该被注解方法。

Method 属性的取值为 RequestMethod 枚举常量。常用的为 RequestMethod.GET 与 RequestMethod.POST,分别表示提交方式的匹配规则为 GET 与 POST 提交。

public class MyController {
    
    //指定some.do使用get请求方式
    @RequestMapping(value = "/first.do",method = RequestMethod.GET)

客户端浏览器常用的请求方式,及其 提交方式有以下几种:

处理器方法的参数

处理器方法可以包含以下四类参数,这些参数会在系统调用时由系统自动赋值,即程序 员可在方法内直接使用。

HttpServletRequestHttpServletResponseHttpSession请求中所携带的请求参

public ModelAndView doFirst(HttpServletRequest request,
                                HttpServletResponse response,
                                HttpSession session){
        ModelAndView mv  = new ModelAndView();
        mv.addObject("msg","====欢迎使用springmvc做web开发====" + request.getParameter("name"));
逐个参数接收

只要保证请求参数名与该请求处理方法的参数名相同即可。

@Controller
public class MyController {


    
    @RequestMapping(value = "/receiveproperty.do")
    public ModelAndView doSome(String name, Integer age){
        System.out.println("doSome, name="+name+"   age="+age);
        //可以在方法中直接使用 name , age
        //处理some.do请求了。 相当于service调用处理完成了。
        ModelAndView mv  = new ModelAndView();
        mv.addObject("myname",name);
        mv.addObject("myage",Integer.valueOf(age));
        //show是视图文件的逻辑名称(文件名称)
        mv.setViewName("show");
        return mv;
    }
}
请求参数中文乱码问题

对于前面所接收的请求参数,若含有中文,则会出现中文乱码问题(get不会,post会)。Spring 对于请求参数中的中文乱码问题,给出了专门的字符集过滤器:spring-web-5.2.5.RELEASE.jar 的 org.springframework.web.filter 包下的 CharacterEncodingFilter 类。

在 web.xml 中注册字符集过滤器,即可解决 Spring 的请求参数的中文乱码问题。不过, 最好将该过滤器注册在其它过滤器之前。因为过滤器的执行是按照其注册顺序进行的。


    characterEncodingFilter
    org.springframework.web.filter.CharacterEncodingFilter
    
    
        encoding
        utf-8
    
    
    
        forceRequestEncoding
        true
    
    
    
        forceResponseEncoding
        true
    


    characterEncodingFilter
    
        System.out.println("doSome, name="+name+"   age="+age);
        //可以在方法中直接使用 name , age
        //处理some.do请求了。 相当于service调用处理完成了。
        ModelAndView mv  = new ModelAndView();
        mv.addObject("myname",name);
        mv.addObject("myage",age);
        //show是视图文件的逻辑名称(文件名称)
        mv.setViewName("show");
        return mv;
    }
对象参数接收

将处理器方法的参数定义为一个对象,只要保证请求参数名与这个对象的属性同名即可。

定义类 Student:

public class Student {
    private String name;
    private Integer age;
}

index.jsp:

使用java对象接收请求参数

 
    @RequestMapping(value = "/receiveobject.do")
    public ModelAndView receiveParam( Student myStudent){
        System.out.println("receiveParam, name="+myStudent.getName()+"   age="+myStudent.getAge());
        //可以在方法中直接使用 name , age
        //处理some.do请求了。 相当于service调用处理完成了。
        ModelAndView mv  = new ModelAndView();
        mv.addObject("myname",myStudent.getName());
        mv.addObject("myage",myStudent.getAge());
        mv.addObject("mystudent",myStudent);
        //show是视图文件的逻辑名称(文件名称)
        mv.setViewName("show");
        return mv;
    }
对象参数接收

将处理器方法的参数定义为一个对象,只要保证请求参数名与这个对象的属性同名即可。

定义类 Student:

public class Student {
    private String name;
    private Integer age;
}

index.jsp:

使用java对象接收请求参数

 
    @RequestMapping(value = "/receiveobject.do")
    public ModelAndView receiveParam( Student myStudent){
        System.out.println("receiveParam, name="+myStudent.getName()+"   age="+myStudent.getAge());
        //可以在方法中直接使用 name , age
        //处理some.do请求了。 相当于service调用处理完成了。
        ModelAndView mv  = new ModelAndView();
        mv.addObject("myname",myStudent.getName());
        mv.addObject("myage",myStudent.getAge());
        mv.addObject("mystudent",myStudent);
        //show是视图文件的逻辑名称(文件名称)
        mv.setViewName("show");
        return mv;
    }
处理器方法的返回值

使用@Controller 注解的处理器的处理器方法,其返回值常用的有四种类型:

第一种:ModelAndView第二种:String第三种:无返回值 void第四种:返回自定义类型对象

根据不同的情况,使用不同的返回值。

返回 ModelAndView

若处理器方法处理完后,需要跳转到其它资源,且又要在跳转的资源间传递数据,此时 处理器方法返回 ModelAndView 比较好。当然,若要返回 ModelAndView,则处理器方法中 需要定义 ModelAndView 对象。

在使用时,若该处理器方法只是进行跳转而不传递数据,或只是传递数据而并不向任何 资源跳转(如对页面的 Ajax 异步响应),此时若返回 ModelAndView,则将总是有一部分多 余:要么 Model 多余,要么 View 多余。即此时返回 ModelAndView 将不合适。

返回 String

处理器方法返回的字符串可以指定逻辑视图名,通过视图解析器解析可以将其转换为物理视图地址。

    
        
        
        
        
    
@RequestMapping(value = "/returnString-view.do")
public String doReturnView(HttpServletRequest request,String name, Integer age){
    System.out.println("doReturnView, name="+name+"   age="+age);
    //可以自己手工添加数据到request作用域
    request.setAttribute("myname",name);
    request.setAttribute("myage",age);
    // show : 逻辑视图名称,项目中配置了视图解析器
    // 框架对视图执行forward转发 *** 作
    return "show";
}
返回 void(了解)

对于处理器方法返回 void 的应用场景,AJAX 响应.

若处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void。

例如,对于 AJAX 的异步请求的响应。

    maven 加入 jackson 依赖

    由于本项目中服务端向浏览器传回的是 JSON 数据,需要使用一个工具类将字符串包装 为 JSON 格式,所以需要导入 JSON 的依赖。

    
        com.fasterxml.jackson.core
        jackson-core
        2.9.0
    
    
        com.fasterxml.jackson.core
        jackson-databind
        2.9.0
    
    

    引入 jQuery 库

    由于本项目要使用 jQuery 的 ajax()方法提交 AJAX 请求,所以项目中需要引入 jQuery 的 库。在 WebRoot 下新建一个 Folder(文件夹),命名为 js,并将 jquery-1.11.1.js 文件放入其 中。

    当然,该 jQuery 库文件,需要在使用 ajax()方法的 index 页面中引入。

    
    

    index.jsp

    index 页面由两部分内容构成:一个是,用于提交 AJAX 请求;一个是, 用于处理 AJAX 请求。(其他返回值也是这个前端页面)

    
        Title
         
         
    
    
    
    	
    
    

    修改处理器类 MyController

    处理器对于 AJAX 请求中所提交的参数,可以使用逐个接收的方式,也可以以对象的方 式整体接收。只要保证 AJAX 请求参数与接收的对象类型属性同名。

    以逐个方式接收参数:

    //处理器方法返回void, 响应ajax请求
    //手工实现ajax,json数据: 代码有重复的 1. java对象转为json; 2. 通过HttpServletResponse输出json数据
    @RequestMapping(value = "/returnVoid-ajax.do")
    public void doReturnVoidAjax(HttpServletResponse response, String name, Integer age) throws IOException {
        System.out.println("===doReturnVoidAjax====, name="+name+"   age="+age);
        //处理ajax, 使用json做数据的格式
        //service调用完成了, 使用Student表示处理结果
        Student student  = new Student();
        student.setName("张飞同学");
        student.setAge(28);
    
        String json = "";
        //把结果的对象转为json格式的数据
        if( student != null){
            ObjectMapper om  = new ObjectMapper();
            json  = om.writevalueAsString(student);
            System.out.println("student转换的json===="+json);
        }
    
        //输出数据,响应ajax的请求
        response.setContentType("application/json;charset=utf-8");
        PrintWriter pw  = response.getWriter();
        pw.println(json);
        pw.flush();
        pw.close();
    
    }
    
返回对象 Object
现在做ajax, 主要使用json的数据格式。 实现步骤:
   1.加入处理json的工具库的依赖, springmvc默认使用的jackson。
   2.在sprigmvc配置文件之间加入  注解驱动。
     json  = om.writevalueAsString(student);
   3.在处理器方法的上面加入@ResponseBody注解

处理器方法也可以返回 Object 对象。这个 Object 可以是 Integer,String,自定义对象, Map,List 等。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的。

返回对象,需要使用@ResponseBody注解,将转换后的 JSON 数据放入到响应体中。

    maven pom.xml

    由于返回 Object 数据,一般都是将数据转化为了 JSON 对象后传递给浏览器页面的。而 这个由 Object 转换为 JSON,是由 Jackson 工具完成的。所以需要导入 Jackson 的相关 Jar 包。

    
        com.fasterxml.jackson.core
        jackson-core
        2.9.0
    
    
        com.fasterxml.jackson.core
        jackson-databind
        2.9.0
    
    

    声明注解驱动

    将 Object 数据转化为 JSON 数据,需要由消息转换器 HttpMessageConverter 完成。而转 换器的开启,需要由来完成。

    SpringMVC 使用消息转换器实现请求数据和对象,处理器方法返回对象和响应输出之间 的自动转换

    当 Spring 容器进行初始化过程中,在处创建注解驱动时,默认 创建了七个 HttpMessageConverter 对象。也就是说,我们注册,就 是为了让容器为我们创建 HttpMessageConverter 对象。

    HttpMessageConverter接口:消息转换器。
    功能:定义了java转为json,xml等数据格式的方法。 这个接口有很多的实现类。
    这些实现类完成 java对象到json, java对象到xml,java对象到二进制数据的转换

    
    

    controller

     
        @RequestMapping(value = "/returnStudentJson.do")
        @ResponseBody
        public Student doStudentJsonObject(String name, Integer age) {
            //调用service,获取请求结果数据 , Student对象表示结果数据
            Student student = new Student();
            student.setName("李四同学");
            student.setAge(20);
            return student; // 会被框架转为json
    
        }
    
返回 List 集合
 
    @RequestMapping(value = "/returnStudentJsonArray.do")
    @ResponseBody
    public List doStudentJsonObjectArray(String name, Integer age) {

        List list = new ArrayList<>();
        //调用service,获取请求结果数据 , Student对象表示结果数据
        Student student = new Student();
        student.setName("李四同学");
        student.setAge(20);
        list.add(student);

        student = new Student();
        student.setName("张三");
        student.setAge(28);
        list.add(student);


        return list;

    }
返回字符串对象

若要返回非中文字符串,将前面返回数值型数据的返回值直接修改为字符串即可。但若返回的字符串中带有中文字符 , 则 接 收方页面将会出现乱码 。此时需要使用 @RequestMapping 的 produces 属性指定字符集。

注意:ajax中的dataType要改为:text 或者删除dataType

 
    @RequestMapping(value = "/returnStringData.do",produces = "text/plain;charset=utf-8")
    @ResponseBody
    public String doStringData(String name,Integer age){
        return "Hello SpringMVC 返回对象,表示数据";
    }
静态资源访问 配置详解

    *.do

    在没有特殊要求的情况下,SpringMVC 的中央调度器 DispatcherServlet 的 常使用后辍匹配方式,如写为*.do 或者 *.action, *.mvc 等。

    /

可以写为/,因为 DispatcherServlet 会将向静态资源的获取请求,例如.css、.js、.jpg、.png 等资源的获取请求,当作是一个普通的 Controller 请求。中央调度器会调用处理器映射器为 其查找相应的处理器。当然也是找不到的,所以在这种情况下,所有的静态资源获取请求也 均会报 404 错误。

在项目中添加图片:在项目的 WebRoot 下添加一个目录 images,并在其中添加一张图片资源。

修改 index 页面:

 

修改的值:

​ 保持的值为 *.do,扩展名方式,图片会正常显示。

​ 保持的值为 *.do,扩展名方式,图片会正常显示。

静态资源访问

的值并不是说写为/后,静态资源就无法访问了。经过一些配置后,该问 题也是可以解决的。

    使用

    声 明 了 后 , springmvc 框 架 会 在 容 器 中 创 建 DefaultServletHttpRequestHandler 处理器对象。它会像一个检查员,对进入 DispatcherServlet 的 URL 进行筛查,如果发现是静态资源的请求,就将该请求转由 Web 应用服务器默认的 Servlet 处理。一般的服务器都有默认的 Servlet。

    在 Tomcat 中,有一个专门用于处理静态资源访问的 Servlet 名叫 DefaultServlet。其为 default。可以处理各种静态资源访问请求。该 Servlet 注册在 Tomcat 服务 器的 web.xml 中。

​ 只需要在 springmvc.xml 中添加标签即可。


    使用(掌握)

    在 Spring3.0 版本后,Spring 定义了专门用于处理静态资源访问请求的处理器 ResourceHttpRequestHandler。并且添加了标签,专门用于解决静态资源无法访问问题。需要在 springmvc 配置文件中添加如下形式的配置:

     
            //处理some.do请求了。 相当于service调用处理完成了。
            ModelAndView mv  = new ModelAndView();
            mv.addObject("msg","欢迎使用springmvc做web开发");
            mv.addObject("fun","执行的是doSome方法");
            //显示转发
            //mv.setViewName("forward:/WEB-INF/view/show.jsp");
    
            mv.setViewName("forward:/hello.jsp"); //根目录下的hello.jsp
            return mv;
        }
    
    请求重定向

    在处理器方法返回的视图字符串的前面添加 redirect:,则可实现重定向跳转。

    处理器方法定义:

        @RequestMapping(value = "/doRedirect.do")
        public ModelAndView doWithRedirect(String name,Integer age){
            //处理some.do请求了。 相当于service调用处理完成了。
            ModelAndView mv  = new ModelAndView();
            //数据放入到 request作用域
            mv.addObject("myname",name);
            mv.addObject("myage",age);
            //重定向
            //mv.setViewName("redirect:/hello.jsp");
            //http://localhost:8080/ch08_forard_redirect/hello.jsp?myname=lisi&myage=22
    
            //重定向不能访问/WEB-INF资源
            mv.setViewName("redirect:/WEB-INF/view/show.jsp");
            return mv;
        }
    
    
    异常处理
    异常处理步骤:
    1.新建maven web项目
    2.加入依赖
    3.新建一个自定义异常类 MyUserException , 再定义它的子类NameException ,AgeException
    4.在controller抛出NameException , AgeException
    5.创建一个普通类,作用全局异常处理类
      1)在类的上面加入@ControllerAdvice
      2) 在类中定义方法,方法的上面加入@ExceptionHandler
    6.创建处理异常的视图页面
    7.创建springmvc的配置文件
     1)组件扫描器 ,扫描@Controller注解
     2)组件扫描器,扫描@ControllerAdvice所在的包名
     3)声明注解驱动
    
    @ExceptionHandler 注解

    使用注解@ExceptionHandler 可以将一个方法指定为异常处理方法。该注解只有一个可 选属性 value,为一个 Class数组,用于指定该注解的方法所要处理的异常类,即所要匹 配的异常。

    而被注解的方法,其返回值可以是 ModelAndView、String,或 void,方法名随意,方法 参数可以是 Exception 及其子类对象、HttpServletRequest、HttpServletResponse 等。系统会 自动为这些方法参数赋值。

    对于异常处理注解的用法,也可以直接将异常处理方法注解于 Controller 之中。

      自定义异常类

      定义三个异常类:NameException、AgeException、MyUserException。其中 MyUserException 是另外两个异常的父

      //当年龄有问题时,抛出的异常
      public class AgeException extends MyUserException {
          public AgeException() {
              super();
          }
      
          public AgeException(String message) {
              super(message);
          }
      }
      
      //表示当用户的姓名有异常,抛出NameException
      public class NameException extends MyUserException {
          public NameException() {
              super();
          }
      
          public NameException(String message) {
              super(message);
          }
      }
      
      public class MyUserException extends Exception {
          public MyUserException() {
              super();
          }
      
          public MyUserException(String message) {
              super(message);
          }
      }
      

      修改 Controller 抛出异常

      @Controller
      public class MyController {
      
      
          @RequestMapping(value = "/some.do")
          public ModelAndView doSome(String name,Integer age) throws MyUserException {
              //处理some.do请求了。 相当于service调用处理完成了。
              ModelAndView mv  = new ModelAndView();
      
              //try {
                  //根据请求参数抛出异常
                  if (!"zs".equals(name)) {
                      throw new NameException("姓名不正确!!!");
                  }
      
                  if (age == null || age > 80) {
                      throw new AgeException("年龄比较大!!!");
                  }
      
              //}catch(Exception e){
              //   e.printStackTrace();
              //}
      
              mv.addObject("myname",name);
              mv.addObject("myage",age);
              mv.setViewName("show");
              return mv;
          }
      

      定义异常响应页面

      index.jsp:

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <%
          String basePath = request.getScheme() + "://" +
                  request.getServerName() + ":" + request.getServerPort() +
                  request.getContextPath() + "/";
      %>
      
      
          Title
          
      
      
      
           

      处理异常的,全局异常处理

      ageError.jsp:

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      
      
          Title
      
      
         ageError.jsp 
      提示信息:${msg}
      系统异常消息:${ex.message}

      default.jsp:

      
      
          Title
      
      
         defaultError.jsp 
      提示信息:${msg}
      系统异常消息:${ex.message}

      nameError.jsp:

      
      
          Title
      
      
         nameError.jsp 
      提示信息:${msg}
      系统异常消息:${ex.message}

      定义全局异常处理类

      @ControllerAdvice
      public class GlobalExceptionHandler {
          //定义方法,处理发生的异常
          
      
          @ExceptionHandler(value = NameException.class)
          public ModelAndView doNameException(Exception exception){
              //处理NameException的异常。
              
              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){
              //处理AgeException的异常。
             
              ModelAndView mv = new ModelAndView();
              mv.addObject("msg","你的年龄不能大于80");
              mv.addObject("ex",exception);
              mv.setViewName("ageError");
              return mv;
          }
      
          //处理其它异常, NameException, AgeException以外,可能会出现不知类型的异常
          @ExceptionHandler
          public ModelAndView doOtherException(Exception exception){
              //处理其它异常
              ModelAndView mv = new ModelAndView();
              mv.addObject("msg","你的年龄不能大于80");
              mv.addObject("ex",exception);
              mv.setViewName("defaultError");
              return mv;
          }
      }
      

      定义 Spring 配置文件

      
      
      
      
          
          
          
          
      
      
      
      
      
      
      
    拦截器

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

    拦截器的使用步骤:
     1.定义类实现HandlerInterceptor接口
     2.在springmvc配置文件中,声明拦截器, 让框架知道拦截器的存在。
    
    拦截器的执行时间:
      1)在请求处理之前, 也就是controller类中的方法执行之前先被拦截。
      2)在控制器方法执行之后也会执行拦截器。
      3)在请求处理完成后也会执行拦截器。
    
    
    拦截器:看做是多个Controller中公用的功能,集中到拦截器统一处理。使用的aop的思想
    
    一个拦截器的执行
    //拦截器类:拦截用户的请求。
    public class MyInterceptor implements HandlerInterceptor {
    
        private long btime = 0;
        
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            btime = System.currentTimeMillis();
            System.out.println("拦截器的MyInterceptor的preHandle()");
            //计算的业务逻辑,根据计算结果,返回true或者false
            //给浏览器一个返回结果
            //request.getRequestDispatcher("/tips.jsp").forward(request,response);
            return true;
        }
    
        
        @Override
        public void postHandle(HttpServletRequest request,
                               HttpServletResponse response,
                               Object handler, ModelAndView mv) throws Exception {
            System.out.println("拦截器的MyInterceptor的postHandle()");
            //对原来的doSome执行结果,需要调整。
            if( mv != null){
                //修改数据
                mv.addObject("mydate",new Date());
                //修改视图
                mv.setViewName("other");
            }
        }
    
        
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                    Object handler, Exception ex) throws Exception {
            System.out.println("拦截器的MyInterceptor的afterCompletion()");
    
            long etime = System.currentTimeMillis();
            System.out.println("计算从preHandle到请求处理完成的时间:"+(etime - btime ));
        }
    }
    
    @Controller
    public class MyController {
    
        @RequestMapping(value = "/some.do")
        public ModelAndView doSome(String name,Integer age)  {
            System.out.println("=====执行MyController中的doSome方法=====");
            //处理some.do请求了。 相当于service调用处理完成了。
            ModelAndView mv  = new ModelAndView();
            mv.addObject("myname",name);
            mv.addObject("myage",age);
            mv.setViewName("show");
            return mv;
        }
    
    }
    
     
        
            
            
                
                
                
                
            
        
    

    拦截器中方法与处理器方法的执行顺序如下图:

    多个拦截器的执行
    
        
        
            
            
            
        
        
        
            
            
        
    
    
    多个拦截器:
    第一个拦截器preHandle=true , 第二个拦截器preHandle=true 
    
    111111-拦截器的MyInterceptor的preHandle()
    22222-拦截器的MyInterceptor的preHandle()
    =====执行MyController中的doSome方法=====
    22222-拦截器的MyInterceptor的postHandle()
    111111-拦截器的MyInterceptor的postHandle()
    22222-拦截器的MyInterceptor的afterCompletion()
    111111-拦截器的MyInterceptor的afterCompletion()
    
    ---------------------------------------------------
    第一个拦截器preHandle=true , 第二个拦截器preHandle=false(只要有一个为false controller都不会执行)
    
    111111-拦截器的MyInterceptor的preHandle()
    22222-拦截器的MyInterceptor的preHandle()
    111111-拦截器的MyInterceptor的afterCompletion()
    
    ----------------------------------------------------------
    第一个拦截器preHandle=false , 第二个拦截器preHandle=true|false
    
    111111-拦截器的MyInterceptor的preHandle()
    

    当有多个拦截器时,形成拦截器链。拦截器链的执行顺序,与其注册顺序一致。需要再 次强调一点的是,当某一个拦截器的 preHandle()方法返回 true 并被执行到时,会向一个专 门的方法栈中放入该拦截器的 afterCompletion()方法。

    多个拦截器中方法与处理器方法的执行顺序如下图:

    从图中可以看出,只要有一个 preHandle()方法返回 false,则上部的执行链将被断开, 其后续的处理器方法与 postHandle()方法将无法执行。但,无论执行链执行情况怎样,只要 方法栈中有方法,即执行链中只要有 preHandle()方法返回 true,就会执行方法栈中的 afterCompletion()方法。最终都会给出响应。

    拦截器和过滤器的区别
      过滤器是servlet中的对象, 拦截器是框架中的对象过滤器实现Filter接口的对象, 拦截器是实现HandlerInterceptor过滤器是用来设置request,response的参数,属性的,侧重对数据过滤的。 拦截器是用来验证请求的,能截断请求。过滤器是在拦截器之前先执行的。过滤器是tomcat服务器创建的对象;拦截器是springmvc容器中创建的对象过滤器是一个执行时间点;拦截器有三个执行时间点过滤器可以处理jsp,js,html等等
      拦截器是侧重拦截对Controller的对象。 如果你的请求不能被DispatcherServlet接收, 这个请求不会执行拦截器内容拦截器拦截普通类方法执行,过滤器过滤servlet请求响应
    权限拦截器举例

    只有经过登录的用户方可访问处理器,否则,将返回“无权访问”提示。

    本例的登录,由一个 JSP 页面完成。即在该页面里将用户信息放入 session 中。也就是 说,只要访问过该页面,就说明登录了。没访问过,则为未登录用户。

      定义权限拦截器

      //拦截器类:拦截用户的请求。
      public class MyInterceptor implements HandlerInterceptor {
      
      
          //验证登录的用户信息, 正确return true,其它return false
          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
              System.out.println("111111-拦截器的MyInterceptor的preHandle()");
              String loginName = "";
              //从session中获取name的值
              Object attr  = request.getSession().getAttribute("name");
              if( attr != null){
                  loginName = (String)attr;
              }
      
              //判断登录的账户,是否符合要求
              if( !"zs".equals(loginName)){
                  //不能访问系统
                  //给用户提示
                  request.getRequestDispatcher("/tips.jsp").forward(request,response);
                  return false;
              }
      
              //zs登录
              return true;
          }
      
      
      }
      

      login.jsp

      
          模拟登录,zs登录系统
          <%
              session.setAttribute("name","zs");
          %>
      
      
      

      tips.jsp

      
        tips.jsp  非zs不能访问系统
      
      

      index.jsp

      
      
          

      一个拦截器

    欢迎分享,转载请注明来源:内存溢出

    原文地址: http://outofmemory.cn/zaji/5708944.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存