Springmvc核心技术

Springmvc核心技术

请求转发和重定向

在这里插入图片描述
请求转发代码示例:

@Controller
public class MyController {
    /*
    * 逐个接收参数:
    *   要求:控制器方法的形参名和请求中参数名必须一致
    *        同名的请求参数赋值给同名的形参
    * */
    @RequestMapping(value = "/doForward.do")
    public ModelAndView doSome(String name, Integer age){   //doGet方法
        /*
        *  处理器方法返回ModelAndView,实现转发forward
        *   语法:setViewName("forward:视图完整路径")
        *   forward不和视图解析器一同使用,当作项目中没有视图解析器
        * */
        ModelAndView mv = new ModelAndView();
        //添加数据
        //框架最后将数据放到request作用域
        mv.addObject("myname", name);
        mv.addObject("myage", age);

        //使用forward操作,显示转发,用在转发到非视图解析器规定的页面
        mv.setViewName("forward:/WEB-INF/view/show.jsp");

        //最后返回mv
        return mv;
    }
}

重定向代码示例:

@Controller
public class MyController {
    @RequestMapping(value = "/doRedirect.do")
    public ModelAndView doSome(String name, Integer age){   //doGet方法
        /*
        *  处理器方法返回ModelAndView,实现重定向Redirect
        *   语法:setViewName("Redirect:视图完整路径")
        *   Redirect不和视图解析器一同使用,当作项目中没有视图解析器
        *
        *   框架对重定向的操作:
        *     1.框架会把Model中的简单类型的数据,转为String使用,作为hello.jsp的get请求参数使用
        *       目的是在doRedirect.do请求和hello.jsp请求之间传递数据
        *     2.在目标hello.jsp页面可以使用参数集合对象${param.参数}获取请求参数值
        *       例如:${param.myname}
        *     3.redirect不能访问受保护的/WEB/INF下的资源,/WEB/INF下的资源不能从外部直接访问
        * */
        ModelAndView mv = new ModelAndView();
        //添加数据
        //在重定向中,框架会把参数加入到重定向的url地址中,但是request域中是没有数据的,所以需要使用${param.myname}获取参数数据
        mv.addObject("myname", name);
        mv.addObject("myage", age);

        //使用Redirect操作,显示转发,用在转发到非视图解析器规定的页面
        mv.setViewName("redirect:/hello.jsp");

        //最后返回mv
        return mv;
    }
}

异常处理

框架采用统一全局的异常处理方案,基于AOP的思想,把Controller中的异常统一集中到一个地方,集中进行处理。将业务逻辑和异常处理分开。也就是解耦合。
使用两个注解:
1.@ExceptionHandler
2.@ControllerAdvice
在这里插入图片描述

异常的集中处理:

1.定义一个自定义异常类(MyUserException):

package com.exception;

public class MyUserException extends Exception{
    public MyUserException() {
        super();
    }

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

2.定义上面异常类的子类(AgeException, NameException):

package com.exception;

//表示当用户的姓名有异常,抛出AgeException
public class AgeException extends MyUserException{
    public AgeException() {
        super();
    }

    public AgeException(String message) {
        super(message);
    }
}
package com.exception;

//表示当用户的姓名有异常,抛出NameException
public class NameException extends MyUserException{
    public NameException() {
        super();
    }

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

3.创建一个全局异常处理类(GlobalExceptionHandler):

package com.handler;


import com.exception.AgeException;
import com.exception.NameException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;


/*
* @ControllerAdvice: 控制器增强,也就是给控制器增加异常处理功能的
*                   位置:在类的上面
*   特点:需要让框架知道这个注解所在的包名,需要在springmvc配置文件中声明组件扫描器。
*   指定@ControllerAdvice所在的包名
* */
@ControllerAdvice
public class GlobalExceptionHandler {
    //定义方法,处理发生的异常
    /*
    *   处理异常的方法和控制器定义的方法一样,可以有多个参数,返回值也可以是ModelAndView,
    *       String,void对象类型的返回值
    *
    *     形参Exception,表示Controller对象中抛出的异常对象
    *       通过这个形参可以获取发生的异常的详细信息
    *
    *       还需要加@ExceptionHandler ,里面有一个value属性,表示异常的类型,当发生此
    *       异常时由当前的方法处理
    * */
    @ExceptionHandler(value = NameException.class)
    public ModelAndView doNameException(Exception exception){
        //处理NameException的异常
        /*
        *   异常发生处理的逻辑:
        *   1.需要把异常记录下来,记录到数据库,日志文件。
        *       记录异常发生的时间,哪个方法发生的,异常的错误内容。
        *   2.发送通知,把异常消息通过邮件等消息发送给相关人员
        *   3.给用户友好的提示
        * */
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg", "你的姓名必须是zs,其他用户不能访问");
        mv.addObject("ex", exception);
        mv.setViewName("nameError");
        return mv;
    }

    @ExceptionHandler(value = AgeException.class)
    public ModelAndView doAgeException(Exception exception){
        //处理AgeException的异常
        /*
         *   异常发生处理的逻辑:
         *   1.需要把异常记录下来,记录到数据库,日志文件。
         *       记录异常发生的时间,哪个方法发生的,异常的错误内容。
         *   2.发送通知,把异常消息通过邮件等消息发送给相关人员
         *   3.给用户友好的提示
         * */
        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;
    }
}

4.创建异常接收页面(nameError.jsp):

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <p>nameError.jsp</p><br/>
    <P>接收到的错误信息:${msg}</P><br/>
    <p>系统异常消息:${ex.message}</p>
</body>
</html>

拦截器

在这里插入图片描述

拦截器的示例代码:

1.创建拦截器类:

package com.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;

public class MyInterceptor implements HandlerInterceptor {
    private long btime = 0;

    /*
    *  preHandle叫做预处理方法
    *  参数:
    *       Object handler: 被拦截的控制器对象
    *  返回值boolean:
    *   true:请求是通过了拦截器的验证,可以执行控制器的方法。
    *   false:请求的没有通过拦截器的验证,请求到达拦截器就停止了。
    *
    *   特点:
    *     1.方法在控制器方法执行前先执行的,用户的请求首先到达此方法
    *     2.在这个方法中,可以获取请求的信息,验证请求是否符合要求。
    *       可以验证用户是否登录,验证用户是否具有权限访问某个资源。
    *       验证失败,可以截断请求,请求不能被处理。
    *       验证成功,可以放行请求,此时控制器请求才能被执行。
    * */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        btime = System.currentTimeMillis();
        System.out.println("这是拦截器的preHandle方法");
        return true;//如果返回假,请求就结束了,可以设计一个提示页面,作为用户交互
    }

    /*
    *   postHandle:后处理方法
    *     参数:
    *       Object handler:被拦截的处理器对象
    *       ModelAndView modelAndView: 处理器方法的返回值
    *
    *     特点:
    *       1.在处理器方法执行后执行的。
    *       2.能够获取到处理器方法的返回值ModelAndView,可以对ModelAndView
    *         中的数据和视图,可以影响到最后的执行结果。
    *       3.主要是对原来的执行结果进行二次修正。
    * */

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, 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, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        long etime = System.currentTimeMillis();
        System.out.println("计算从prehandle到请求处理结束的时间: " + (etime - btime));
    }
}

2.配置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">

     <!--声明组件扫描器,扫描Controller注解-->
    <context:component-scan base-package="com.controller"/>

<!--    声明springmvc框架中的视图解析器,帮助开发人员设置视图文件的路径-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--有两个属性,一个是前缀,另外一个是后缀-->
        <!--前缀:视图文件的路径,前面的‘/’代表根,后面的‘/’代表路径-->
        <property name="prefix" value="/WEB-INF/view/"/>
        <!--后缀:表示视图文件的扩展名-->
        <property name="suffix" value=".jsp"/>
    </bean>


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

多个拦截器的执行顺序

执行的顺序是按照声明的顺序执行的。
在这里插入图片描述
拦截器和过滤器的区别:
在这里插入图片描述

使用拦截器,实现的用户登录验证的例子:

在这里插入图片描述

springmvc执行的流程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值