高级第六天:SpringMVC第3天

2020-09-07  本文已影响0人  w漫漫

SpringMVC第三天

主要内容

1.拦截器的简介

2.拦截器内容详解

3.多拦截器质性顺序

4.SpringMVC中异常处理

5.SpringMVC中注解

一.拦截器的简介

1.遇到的问题

在之前学习Servlet的时候,我们学习了过滤器的知识.过滤器的作用是保护请求的服务器资源,在请求资源被执行之前,如果请求地址符合拦截范围,则会先执行过滤器.过滤器的执行时机,是在Servlet之前执行的.但是在使用了SpringMVC后,Servlet只有一个了,也就是DispatcherServlet.那么,如果我们仍然使用过滤器来完成请求的拦截,因为过滤器是在Servlet之前执行的,就会造成,过滤器会拦截DispatcherServlet所有的请求.那么,如果我们有部分请求不想被拦截.怎么办?

2.解决方案机制

拦截器使用

3.理解示意图

4.拦截器的概念

SpringMVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并做响应的处理.例如通过拦截器可以进行权限验证,记录请求信息的日志,判断用户是否登录等.

要使用SpringMVC中的拦截器,就需要对拦截器类进行定义和配置.通常拦截器类可以通过两种方式来定义

1.通过实现HandlerInterceptor接口,或继承HandlerInterceptor接口的实现类(如HandlerInterceptorAdapter)来定义

2.通过实现WebRequestInterceptor接口,或继承We bRequestInterceptor接口的实现类来定义

5.拦截器和过滤器的区别

(1)拦截器SpringMVC的,而过滤器是servlet的.

(2)拦截器不依赖与servlet容器,过滤器依赖与servlet容器

(3)拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用

(4)拦截器可以访问action上下文,值栈里的对象,而过滤器不能访问

(5)在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

(6)拦截器可以获取IOC容器中的各个bean,而过滤器就不太方便,这点很重要,在拦截器里注入一个service,可以调用业务逻辑

6.代码实现

6.1编写一个普通类实现HandlerInterceptor接口

public class HandlerInterceptorDemo1 implements HandlerInterceptor{

    @Override

    public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throws Exception{

        System.out.println("preHandler拦截器拦截了");

        return true;

    }

    @Override

    public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler ModelAndView modelAndView)throws Exception{

        System.out.println("postHandler方法执行了");

    }

    @Override

    public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handle,Exception ex)throws Exception{

        System.out.println("afterCpmpletion方法执行了");

    }

}

6.2配置拦截器

<mvc:interceptors>

    <mvc:interceptor>

        <mvc:mapping path="/test"/>

        <bean id="handlerInterceptorDemo1" class="com.bjsxt.controller.interceptor.HandlerceptorDemo1"></bean>

    </mvc:interceptor>

</mvc:interceptors>

二.拦截器内容详解

1.preHandle方法

执行时机

再进入控制单元方法之前执行

如何调用

按拦截器定义顺序调用

具体作用

如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回true.如果程序员决定不需要再调用其他的组件去处理请求,则返回false

参数详解

    HttpServletRequest args0,拦截的请求的request对象

    HttpServletResponse arg1,拦截的请求的response对象

    Object args2    封存了单元方法对象的HandlerMethod对象

代码实现

@Override

public boolean preHandler(HttpServletRequest request,HttpServletResponse resp,Object o)throws Exception{

    //作用一:进行中文乱码的处理

    //request.setCharacterEncoding("utf-8");

    //作用二:进行页面的升级和页面的跳转

    //resp.sendRedirect(request.getContextPath()+"/error.jsp");

    System.out.println("preHandle--"+o);

    //作用三:登录用户权限的校验

    return true;

}

2.postHandle方法

执行时机

在进行数据处理和做出响应之间进行这个方法的调用

如何调用

在拦截器链内所有拦截器返回成功调用

具体作用

在业务处理器处理请求后,但是DispatcherServlet向客户低端返回响应前被调用,在该方法中对用户请求request进行处理

参数详解

    HttpServletRequest arg0,拦截的请求的request对象,

    HttpServletResponse arg1,拦截的请求的response对象

    Object arg2,封存了单元方法对象的HandlerMethod对象

    ModelAndView arg3 封存了单元方法的返回值资源路径和请求转到的Map数据

代码实现

@Override

public void postHandle(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,Object o,ModelAndView modelAndView)throws Exception{

    //作用一:进行后期页面跳转页面维护修改的操作

    //modelAndView.setViewName("main2");

    //作用二:进行恶意字符的替换

    Map<String,Object>map = modelAndView.getModel();

    //登录失败枪支

    String str = (String)map.get("msg");

    if(str.contains("枪支")){

        //登录失败**

        String str2 = str.replaceAll("枪支","**");

        map.put("msg",str2);

    }

    System.out.println("postHandle---");

}

3.afterCompletion方法

执行时机

在进行页面渲染的时候执行

如何调用

按拦截器定义逆序调用

具体作用

在DispatcherServlet完全处理请求后被调用,可以在该方法中进行套一些资源清理的操作

参数详解

HttpServletRequest arg0,拦截的请求的request对象

HttpServletResponse arg1,拦截的请求的response对象

Object arg2,封存了单元方法对象的HandlerMethod对象

Exception arg3存储了责任链的异常信息

代码实现

public void afterCompletion(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,Object o,Exception e)throws Exception{

    Syste.out.println("afterCompletion--");

}

三.多个拦截器的执行顺序

1.多个拦截器执行顺序

多个拦截器同时存在时,执行的顺序由配置顺序决定.先配置谁,谁就先执行,多个拦截器可以理解为拦截器栈,先进后出(后进先出),如图所示

2.代码实现

[1]拦截器1的代码

public class handlerInterceptorDemo1 implements HandlerInterceptor{

    @Override

    public boolean preHandle(HttpServletRequest,HttpServletResponse response,Object handler)throws Exception{

        System.out.println("拦截器1:preHandler拦截器拦截了");

        return true;

    }

    @Override

    public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView)throws Exception{

        System.out.println("拦截器1:postHandle方法执行了");

    }

    @override

    public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception{

        System.out.println("拦截器1:afterCompletion方法执行了");

    }

}

[2]拦截器二的代码

public class HandlerInterceptiorDemo2 implements HandlerInterceptor{

    @Override

    public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throws Exception{

        System.out.println("拦截器2:preHandle拦截器拦截了");

        return true;

    }

    @Override

    public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView)throws Exception{

        System.out.println("拦截器2:postHandle方法执行了");

    }

    @Override

    public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception{

        System.out.println("拦截器2:afterCompletion方法执行了");

    }

    @Override

    public void afterCompletion(HttpServletRequest request ,HttpServletResponse response,Object handler,Exception ex)throws Exception{

        System.out.println("拦截器2:afterCompletion方法执行了");

    }

}

[3]拦截器配置

<!--配置拦截器的作用范围-->

<mvc:interceptors>

    <mvc:interceptor>

        <mvc:mapping path="/**"/>

            <bean id="handlerInterceptorDemo1" class="com.sxt.controller.interceptor.HandlerInterceptorDemo1"></bean>

    </mvc:interceptor>

    <mvc:interceptor>

        <mvc:mapping path="/**"/>

        <bean id="handlerInterceptorDemo2" class="com.bjsxt.controller.interceptor.HandlerInterceptorDemo2"></bean>

    </mvc:interceptor>

</mvc:interceptors>

[4]执行结果

四.SpringMVC中异常处理

1.SpringMVC异常简介

系统中异常包括两类:预期异常也运行室异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发,测试通过手段减少运行时异常的发生.

系统的dao,service,controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图

2.异常处理具体实现

a.使用@ExceptionHandler注解处理异常

@ExceptionHandler(value={java.lang.ArithmeticException.class,java.lang.NullPointerException.class})

public ModelAndView handlerArithmeticException(Exception e){

    System.out.println(e);

    ModelAndView mv = new ModelAndView();

    mv.addObject("msg",e);

    mv.setViewName("error1");

    return mv;

}

缺点:只能处理当前COntroller中的异常

b.使用:@ControllerAdvice+@ExceptionHandler

//全局异常处理器

@ControllerAdvice

public class GlobalException{

    @ExceptionHandler(value={java.lang.ArithmeticException.class,java.lang.NullPointerException.class})

    public ModelAndView handlerArithmeticException(Exception e){

        System.out.println(e);

        ModelAndView mv = new ModelAndView();

        mv.addObject("msg",e);

        mv.setViewName("error1");

        return mv;

    }

}

c.使用:SimpleMappingExceptionResolver

//全局异常

@Configuration

public class GloableException2{

    @Bean

    public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){

        SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();

        Properties prop = new Properties();

        prop.put("java.lang.NullPointerException","error1");

        prop.put("java.lang.ArithmeticException","error2");

        resolver.setExceptionMapping(prop);

        return resolver;

    }

}

d.自定义的HandlerExceptionResolve

/**

全局异常

HandlerExceptionResolve

*/

@Configuration

public class GloableException3 implements HandlerExceptionResolver{

    @Override

    public ModelAndView resolverException(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,Object o,Exception e){

        ModelAndView mv = new ModelAndView();

        if(e instanceof NullPointerException){

            mv.setViewName("error1");

        }

        if(e instanceof ArithmeticException){

            mv.setViewName("error2");

        }

        mv.addObject("msg",e);

        return mv;

    }

}

五.SpringMVC中注解完结

1.@Postmapping

作用:指定当前发送请求的方式只可以是post请求

属性

和@RequestMapping中属性一致

代码实现

@PostMapping("/userControllerA")

public String userControllerA(){

    return "forward:/success.jsp";

}

2.@GetMapping

作用:

指定当前发送请求的方式只可以是get请求

属性

和@RequestMapping中属性一致

嗲am实现

@GetMapping("/userControllerA")

public String userControllerA(){

    return "forward:/success.jsp";

}

3.@RestController

作用

书写到类上,代表该类中所有控制单元方法均是ajax响应,相当于@ResponseBody+@Controller

属性:

其中的属性和@Controller中一样

代码实现:

@RestController

public class UserController{}

4.@JsonFormat

作用

处理响应json数据的处理

属性

pattern:指定响应时间日期的格式

Timezone:指定响应的时区,否则会有8个小时的时间差

代码实现:

@DateTimeFormat(pattern="yyyy-MM-dd")

@JsonFormat(pattern="yyyy-MM-dd",timezone="GMT+8")

private Date birth;

5.@CrossOrigin

5.1什么是跨域

由于浏览器的同源策略限制.同于策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源岑略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现.同源策略hi阻止一个域的javascript脚本和另外一个域的内容进行交互.所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

http://127.0.0.1:8080/sxt/index.jsp 协议不一样

http://192.168.232.132:8080/sxt/index.jsp ip不一样

http://127.0.0.1:8888/sxt/index.jsp 端口不一致

http://localhost:8080/sxt/index/jsp ip不一致

作用:

解决了ajax请求之间的跨域问题

属性:

origins:允许可访问的域列表

maxAge:准备响应前的缓存持续的最大时间(以秒为单位)

代码实现:

@CrossOrigin(origins="http://domain2.com",maxAge=3600)

@RestController

@Requestmapoing("/account")

public class AccountController{

    @GetMapping("/{id}")

    public Account retrieve(@PathVariable Long id){}

}

上一篇下一篇

猜你喜欢

热点阅读