SpringMVC核心技术

SpringMVC核心技术,第1张

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

目录一、请求转发和重定向1. 请求转发2. 请求重定向二、异常处理1. 异常处理步骤:1. 自定义异常类2. 修改 Controller 抛出异常3. 定义全局异常处理类4. 定义异常响应页面5. springmvc的配置文件三、拦截器1. 拦截器使用步骤2. 一个拦截器的执行3. 多个拦截器的执行4. 拦截器和过滤器的区别

一、请求转发和重定向

当处理器对请求处理完毕后,向其它资源进行跳转时,有两种跳转方式:请求转发与重定向。而根据所要跳转的资源类型,又可分为两类:跳转到页面与跳转到其它处理器

注意,对于请求转发的页面,可以是WEB-INF中页面;而重定向的页面,是不能为WEB-INF中页的。因为重定向相当于用户再次发出一次请求,而用户是不能直接访问 WEB-INF 中资源的

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

forward:表示转发,实现 request.getRequestdispatcher("xx.Jsp").forward()

redirect:表示重定向,实现 response.sendRedirect("xxx.Jsp")

1. 请求转发

处理器方法返回 ModelAndVIEw 时,需在 setVIEwname()指定的视图前添加 forward:,且此时的视图不再与视图解析器一同工作,这样可以在配置了解析器时指定不同位置的视图。视图页面必须写出相对于项目根的路径。forward *** 作不需要视图解析器。
处理器方法返回 String,在视图路径前面加入 forward: 视图完整路径

还是第一个案例中

    /**     * 处理器方法返回ModelAndVIEw,实现转发forward     * 语法: setVIEwname("forward:视图文件完整路径")     * forward特点: 不和视图解析器一同使用,就当项目中没有视图解析器,不受视图解析器的限制了     */    @RequestMapPing(value = "/doForward.do")    public ModelAndVIEw doForward(String name,Integer age){        ModelAndVIEw mv = new ModelAndVIEw();        mv.addobject("myname",name);        mv.addobject("myage",age);//        mv.setVIEwname("show");        //显式转发//        mv.setVIEwname("forward:/WEB-INF/vIEw/show.Jsp");        // 配置了视图解析器,但是这个文件不在vIEw目录之下就可以使用这样的方法,因为forward不受视图解析器的限制        mv.setVIEwname("forward:/hello.Jsp");        return mv;    }
2. 请求重定向

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

 /**     * 处理器方法返回ModelAndVIEw,实现重定向redirect     * 语法:setVIEwname("redirect:视图完整路径")     * redirect特点: 不和视图解析器一同使用,就当项目中没有视图解析器     *     * 框架对重定向的 *** 作:     * 1.框架会把Model中的简单类型的数据,转为string使用,作为hello.Jsp的get请求参数使用。     *   目的是在 doRedirect.do 和 hello.Jsp 两次请求之间传递数据     *     * 2.在目标hello.Jsp页面可以使用参数集合对象 ${param}获取请求参数值     *    ${param.myname}     *     * 3.重定向不能访问/WEB-INF资源     */    @RequestMapPing(value = "/doRedirect.do")    public ModelAndVIEw doRedirect(String name,age);        //重定向        mv.setVIEwname("redirect:/hello.Jsp");        // 相当于这样,内部作为get请求,通过param可以获取的到        //http://localhost:8080/08_forword/hello.Jsp?myname=lisi&myage=22        //重定向不能访问/WEB-INF资源//        mv.setVIEwname("redirect:/WEB-INF/vIEw/show.Jsp");        return mv;    }
二、异常处理

SpringMVC 框架处理异常的常用方式:使用@ExceptionHandler 注解处理异常

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

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

1. 异常处理步骤:新建maven web项目加入依赖新建一个自定义异常类 MyUserException,再定义它的子类nameException,AgeException在controller抛出nameException,AgeException创建一个普通类,作用全局异常处理类在类的上面加入@ControllerAdvice在类中定义方法,方法的上面加入@ExceptionHandler创建处理异常的视图页面创建springmvc的配置文件组件扫描器 ,扫描@Controller注解组件扫描器,扫描@ControllerAdvice所在的包名声明注解驱动1. 自定义异常类

MyUserException是父类

package com.md.exception;/** * @author MD * @create 2020-08-14 20:31 */public class MyUserException extends Exception {    public MyUserException() {        super();    }    public MyUserException(String message) {        super(message);    }}//-------------------------------package com.md.exception;/** * 当用户的年龄有异常抛出AgeException * @author MD * @create 2020-08-14 20:33 */public class AgeException extends MyUserException {    public AgeException() {        super();    }    public AgeException(String message) {        super(message);    }}//----------------------------package com.md.exception;/** * 当用户的姓名有异常抛出nameException * @author MD * @create 2020-08-14 20:32 */public class nameException extends MyUserException {    public nameException() {        super();    }    public nameException(String message) {        super(message);    }}
2. 修改 Controller 抛出异常
    /**     *此时抛出的异常是下面两个异常的父类     */    @RequestMapPing(value = "/some.do")    public ModelAndVIEw doSome(String name,Integer age) throws MyUserException {        ModelAndVIEw mv = new ModelAndVIEw();        mv.addobject("myname",age);        // 根据请求参数抛出异常        if (!"md".equals(name)){            throw new nameException("姓名不正确");        }        if (age == null || age > 100){            throw new AgeException("年龄有误");        }        mv.setVIEwname("show");        return mv;    }
3. 定义全局异常处理类
package com.md.handler;import com.md.exception.AgeException;import com.md.exception.nameException;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.servlet.ModelAndVIEw;/** * @author MD * @create 2020-08-14 20:38 *//** * @ControllerAdvice : 控制器增强(也就是说给控制器类增加功能--异常处理功能) *  位置:在类的上面。 *  特点:必须让框架知道这个注解所在的包名,需要在springmvc配置文件声明组件扫描器。 *  指定@ControllerAdvice所在的包名 */@ControllerAdvicepublic class GlobalException {    //定义方法,处理发生的异常    /*        处理异常的方法和控制器方法的定义一样, 可以有多个参数,可以有ModelAndVIEw,String,voID,对象类型的返回值        形参:Exception,表示Controller中抛出的异常对象。        通过形参可以获取发生的异常信息。        @ExceptionHandler(异常的class):表示异常的类型,当发生此类型异常时,        由当前方法处理     */    @ExceptionHandler(value = nameException.class)    public ModelAndVIEw donameException(Exception ex) {        // 处理nameException异常        /*           异常发生处理逻辑:           1.需要把异常记录下来, 记录到数据库,日志文件。             记录日志发生的时间,哪个方法发生的,异常错误内容。           2.发送通知,把异常的信息通过邮件,短信,微信发送给相关人员。           3.给用户友好的提示。         */        ModelAndVIEw mv = new ModelAndVIEw();        mv.addobject("msg","姓名是md,其他用户不能访问");        mv.addobject("ex",ex);        mv.setVIEwname("nameError");        return mv;    }    @ExceptionHandler(value = AgeException.class)    public ModelAndVIEw doAgeException(Exception ex) {        // 处理AgeException异常        /*           异常发生处理逻辑:           1.需要把异常记录下来, 记录到数据库,日志文件。             记录日志发生的时间,哪个方法发生的,异常错误内容。           2.发送通知,把异常的信息通过邮件,短信,微信发送给相关人员。           3.给用户友好的提示。         */        ModelAndVIEw mv = new ModelAndVIEw();        mv.addobject("msg","年龄过大");        mv.addobject("ex",ex);        mv.setVIEwname("AgeError");        return mv;    }    // 这个只能有一个,也就是万能的异常处理方法    // 处理其他异常,nameException、AgeException之外的异常,也就是除了自定义之外的异常都能处理    @ExceptionHandler    public ModelAndVIEw doOtherException(Exception ex) {        // 处理OtherException异常        ModelAndVIEw mv = new ModelAndVIEw();        mv.addobject("msg","404");        mv.addobject("ex",ex);        mv.setVIEwname("defaultError");        return mv;    }}
4. 定义异常响应页面

nameError.Jsp

<%--  Created by IntelliJ IDEA.  User: MD  Date: 2020/8/14  Time: 20:54  To change this template use file | Settings | file Templates.--%><%@ page ContentType="text/HTML;charset=UTF-8" language="java" %><HTML><head>    <Title>Title</Title></head><body>    <h1>nameError.Jsp</h1>    <h2>提示:${msg}</h2>    <h2>系统异常信息:${ex.message}</h2></body></HTML>
<h1>ageError.Jsp</h1><h2>提示:${msg}</h2><h2>系统异常信息:${ex.message}</h2><%--和上面都一样,这里就省略了--%><h1>defaultError.Jsp</h1><h2>提示:${msg}</h2><h2>系统异常信息:${ex.message}</h2>
5. springmvc的配置文件
<?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.md.controller"/>    <!--声明springmvc框架中的视图解析器,帮助开发人员设置视图文件路径-->    <bean >        <!--前缀:视图文件的路径-->        <property name="prefix" value="/WEB-INF/vIEw/" />        <!--后缀:视图文件的扩展名-->        <property name="suffix" value=".Jsp"/>    </bean>            <!-- 处理异常的两个步骤	1. 注册组件扫描器,也即是@ControllerAdvice注解所在的包名	2. 注册注解驱动,-->    <context:component-scan base-package="com.md.handler"/>    <mvc:annotation-driven/></beans>

这样就可以了

三、拦截器

SpringMVC 中的 Interceptor 拦截器是非常重要和相当有用的,它的主要作用是拦截指定的用户请求,并进行相应的预处理与后处理。

拦截器是springmvc中的一种,需要实现handlerinterceptor接口。拦截器和过滤器类似,功能方向侧重点不同。 过滤器是用来过滤器请求参数,设置编码字符集等工作。拦截器是拦截用户的请求,做请求做判断处理的。拦截器是全局的,可以对多个Controller做拦截, 一个项目中可以有0个或多个拦截器, 他们在一起拦截用户的请求。拦截器常用在:用户登录处理,权限检查, 记录日志。1. 拦截器使用步骤新建maven web项目加入依赖创建Controller类创建一个普通类,作为拦截器使用实现handlerinterceptor接口实现接口中的三个方法创建show.Jsp创建springmvc的配置文件组件扫描器 ,扫描@Controller注解声明拦截器,并指定拦截的请求uri地址2. 一个拦截器的执行

Controller类

    @RequestMapPing(value = "/some.do")    public ModelAndVIEw doSome(String name,Integer age) {        System.out.println("-------MyController的doSome()");        ModelAndVIEw mv = new ModelAndVIEw();        mv.addobject("myname",age);        mv.setVIEwname("show");        return mv;    }

还是在之前的项目中,定义个普通类,作为拦截器

package com.md.handler;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;/** * 拦截器类,拦截用户的请求 * @author MD * @create 2020-08-14 21:18 */public class MyInterceptor implements handlerinterceptor {// 快捷键:ctrl + O    private long btime = 0;    /*     * preHandle叫做预处理方法。     *   重要:是整个项目的入口,门户。 当preHandle返回true 请求可以被处理。     *        preHandle返回false,请求到此方法就截止。     *     * 参数:     *  Object handler : 被拦截的控制器对象     * 返回值boolean     *   true:请求是通过了拦截器的验证,可以执行处理器方法     *   执行顺序            拦截器: preHandle()            -------MyController的doSome()            拦截器: postHandle()            拦截器: afterCompletion()         *     *   false:请求没有通过拦截器的验证,请求到达拦截器就截止了。 请求没有被处理     *   仅仅输出这一句话,*      拦截器: preHandle()     *     *     *  特点:     *   1.方法在控制器方法(MyController的doSome)之前先执行的。     *     用户的请求首先到达此方法     *     *   2.在这个 方法中可以获取请求的信息, 验证请求是否符合要求。     *     可以验证用户是否登录, 验证用户是否有权限访问某个连接地址(url)。     *      如果验证失败,可以截断请求,请求不能被处理。     *      如果验证成功,可以放行请求,此时控制器方法才能执行。     */    @OverrIDe    public boolean preHandle(httpServletRequest request,httpServletResponse response,Object handler) throws Exception {        btime = System.currentTimeMillis();        System.out.println("拦截器: preHandle()");        // 计算的业务逻辑,根据计算的结果,返回true或者false        //  给浏览器一个反馈//        request.getRequestdispatcher("/tips.Jsp").forward(request,response);////        return false;        return true;    }    /*         postHandle:后处理方法。         参数:          Object handler:被拦截的处理器对象MyController          ModelAndVIEw modelAndVIEw:处理器方法的返回值          特点:           1.在处理器方法之后执行的(MyController.doSome())           2.能够获取到处理器方法的返回值ModelAndVIEw,可以修改ModelAndVIEw中的           数据和视图,可以影响到最后的执行结果。           3.主要是对原来的执行结果做二次修正,           ModelAndVIEw mv = MyController.doSome();           postHandle(request,response,handler,mv);       */    @OverrIDe    public voID postHandle(httpServletRequest request,Object handler,ModelAndVIEw modelAndVIEw) throws Exception {        System.out.println("拦截器: postHandle()");        // 对原来的doSome执行的结果进行调整        if (modelAndVIEw != null){            modelAndVIEw.addobject("mydate",new Date());            modelAndVIEw.setVIEwname("other");        }    }    /*          afterCompletion:最后执行的方法          参数            Object handler:被拦截器的处理器对象            Exception ex:程序中发生的异常          特点:           1.在请求处理完成后执行的。框架中规定是当你的视图处理完成后,对视图执行了forward。就认为请求处理完成。           2.一般做资源回收工作的, 程序请求过程中创建了一些对象,在这里可以删除,把占用的内存回收。         */    @OverrIDe    public voID afterCompletion(httpServletRequest request,Exception ex) throws Exception {        System.out.println("拦截器: afterCompletion()");        long etime = System.currentTimeMillis();        System.out.println("计算从preHandle到请求处理完成的时间:"+(etime - btime ));    }}

创建springmvc的配置文件

<?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.md.controller"/>    <!--声明springmvc框架中的视图解析器,帮助开发人员设置视图文件路径-->    <bean >        <!--前缀:视图文件的路径-->        <property name="prefix" value="/WEB-INF/vIEw/" />        <!--后缀:视图文件的扩展名-->        <property name="suffix" value=".Jsp"/>    </bean>    <!-- 声明拦截器: 拦截器可以一个或者多个-->    <mvc:interceptors>        <!--声明第一个拦截器-->        <mvc:interceptor>            <!-- 指定拦截的请求URL地址,page就是URL地址,可以使用通配符 **,表示任意的字符,文件或者多级目录-->            <!-- http://localhost:8080/user/xxx-->            <!--<mvc:mapPing path="/user/**"/>-->            <mvc:mapPing path="/**"/>            <!--声明拦截器对象-->            <bean />        </mvc:interceptor>    </mvc:interceptors></beans>

拦截器中方法与处理器方法的执行顺序

3. 多个拦截器的执行

再定义一个拦截器

package com.md.handler;public class MyInterceptor implements handlerinterceptor {    @OverrIDe    public boolean preHandle(httpServletRequest request,Object handler) throws Exception {        System.out.println("111111111111拦截器: preHandle()");        return true;    }    @OverrIDe    public voID postHandle(httpServletRequest request,ModelAndVIEw modelAndVIEw) throws Exception {        System.out.println("11111111111111111拦截器: postHandle()");    }    @OverrIDe    public voID afterCompletion(httpServletRequest request,Exception ex) throws Exception {        System.out.println("111111111111111拦截器: afterCompletion()");    }}//---------------------------------------package com.md.handler;public class MyInterceptor2 implements handlerinterceptor {// 快捷键:ctrl + O    @OverrIDe    public boolean preHandle(httpServletRequest request,Object handler) throws Exception {        System.out.println("2222222222222222拦截器: preHandle()");        return false;    }    @OverrIDe    public voID postHandle(httpServletRequest request,ModelAndVIEw modelAndVIEw) throws Exception {        System.out.println("2222222222222222拦截器: postHandle()");    }    @OverrIDe    public voID afterCompletion(httpServletRequest request,Exception ex) throws Exception {        System.out.println("122222222222222222拦截器: afterCompletion()");    }}//---------------------------------------

多个拦截器的注册,在springmvc的配置文件

    <!-- 声明拦截器: 拦截器可以一个或者多个        在框架中保存是在一个ArrayList,先声明的在前面,-->    <mvc:interceptors>        <!--声明第一个拦截器-->        <mvc:interceptor>            <mvc:mapPing path="/**"/>            <!--声明拦截器对象-->            <bean />        </mvc:interceptor>        <!--声明第二个拦截器-->        <mvc:interceptor>            <mvc:mapPing path="/**"/>            <!--声明拦截器对象-->            <bean />        </mvc:interceptor>    </mvc:interceptors>    <!-- 返回的都是true,执行的顺序-->    <!--111111111111拦截器: preHandle()-->    <!--2222222222222222拦截器: preHandle()-->    <!-- -&#45;&#45;&#45;&#45;&#45;&#45;MyController的doSome()-->    <!--2222222222222222拦截器: postHandle()-->    <!--11111111111111111拦截器: postHandle()-->    <!--122222222222222222拦截器: afterCompletion()-->    <!--111111111111111拦截器: afterCompletion()-->    <!-- 第一个true,第一个false,执行顺序-->    <!--111111111111拦截器: preHandle()-->    <!--2222222222222222拦截器: preHandle()-->    <!--111111111111111拦截器: afterCompletion()-->    <!-- 返回的都是false,执行的顺序-->    <!--111111111111拦截器: preHandle()--></beans>

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

4. 拦截器和过滤器的区别过滤器是servlet中的对象, 拦截器是框架中的对象过滤器实现Filter接口的对象, 拦截器是实现handlerinterceptor过滤器是用来设置request,response的参数,属性的,侧重对数据过滤的,拦截器是用来验证请求的,能截断请求。过滤器是在拦截器之前先执行的。过滤器是tomcat服务器创建的对象、拦截器是springmvc容器中创建的对象 总结

以上是内存溢出为你收集整理的SpringMVC核心技术全部内容,希望文章能够帮你解决SpringMVC核心技术所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

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

原文地址: http://outofmemory.cn/langs/1217434.html

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

发表评论

登录后才能评论

评论列表(0条)

保存