请求转发与重定向
请求转发:用户发起一次请求,页面跳转在服务器内部执行。限制:只能访问服务器内部的资源(可以访问WEB-INF中的资源,WEB-INF中的资源是受保护的,用户不能直接访问),不能访问其他服务器的资源。
重定向:用户发起一次请求,服务器接收请求,发现需要跳转其他页面,将跳转连接发送给用户,用户再次发起请求。就是说用户发起两次请求。限制:不能访问WEB-INF下的资源文件,但是可以访问其他服务器的资源。
请求转发
forward:表示转发,实现 :request.getRequestDispatcher(“xx.jsp”).forward()
这与视图解析器冲突。在使用请求转发,不与视图解析器一同工作,解决办法:
ModelAndView mv = new ModelAndView();
mv.setViewName(“forward:/xx.jsp”);
forward:视图的完整路径
forward特点:不与视图解析器一同工作,就当它不存在
重定向
redirect:表示重定向,实现 :response.sendRedirect(“xxx.jsp”)
这与视图解析器冲突。在使用请求转发,不与视图解析器一同工作,解决办法:
ModelAndView mv = new ModelAndView();
mv.setViewName(“redirect:/xx.jsp”);
redirect:视图的完整路径
redirect特点:不与视图解析器一同工作,就当它不存在。这里依然不能访问WEB-INF下的资源文件
异常处理
SpringMVC 框架处理异常的常用方式:使用@ExceptionHandler 注解处理异常。
自定义异常类
继承Exception,重写父类的两个方法
public class NameException extends Exception {
public NameException() {
super();
}
public NameException(String message) {
super(message);
}
}
public class AgeException extends Exception {
public AgeException() {
super();
}
public AgeException(String message) {
super(message);
}
}
定义全局异常处理类
@ControllerAdvice:控制器增强,实际就是增强controller对异常的处理
Controller层的处理器方法发生异常时,会执行@ControllerAdvice修饰的方法,通过@ExceptionHandler匹配异常的类型,对异常进行处理
@ExceptionHandler的参数是异常类
@ControllerAdvice
public class GlobalExceptionHandle {
@ExceptionHandler(value = NameException.class)
public ModelAndView doNameException(Exception ex) {
ModelAndView mv = new ModelAndView();
mv.addObject("tips", "name已存在或格式不正确");
mv.addObject("msg", "@ControllerAdvice处理name的异常");
mv.addObject("exmsg", ex.getMessage());
mv.addObject("ex", ex);
mv.setViewName("error");
return mv;
}
@ExceptionHandler(AgeException.class)
public ModelAndView doAgeException(Exception ex) {
ModelAndView mv = new ModelAndView();
mv.addObject("tips", "age不符合规范");
mv.addObject("msg", "@ControllerAdvice处理age的异常");
mv.addObject("exmsg", ex.getMessage());
mv.addObject("ex", ex);
mv.setViewName("error");
return mv;
}
@ExceptionHandler
public ModelAndView doOtherException(Exception ex) {
ModelAndView mv = new ModelAndView();
mv.addObject("tips", "系统繁忙中,请稍后重试");
mv.addObject("msg", "@ControllerAdvice处理其他类型的异常");
mv.addObject("exmsg", ex.getMessage());
mv.addObject("ex", ex);
mv.setViewName("error");
return mv;
}
}
声明配置文件springmvc.xml
配置扫描器,扫描@ControllerAdvice修饰的类所在的包名
<context:component-scan base-package="com.ljf.handle" />
<mvc:annotation-driven />
拦截器
拦截指定的用户请求,并进行相应的预处理与后处理。
其拦截的时间点在“处理器映射器根据用户提交的请求映射出了所要执行的处理器类,并且也找到了要执行该处理器类的处理器适配器,在处理器适配器执行处理器之前”。当然,在处理器映射器映射出所要执行的处理器类时,已经将拦截器与处理器组合为了一个处理器执行链,并返回给了中央调度器。
一个拦截器
写一个拦截器类实现HandlerInterceptor,并实现preHandler、postHandler、afterCompletion方法
一个拦截器的执行顺序
- preHandler == true
先执行拦截器的preHandler
处理器方法
拦截器的postHandler
在视图处理完成后执行aflterCompletion - preHandler == false
执行拦截器的preHandler
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("执行了拦截器MyInterceptor中的preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView mv) throws Exception {
System.out.println("执行了拦截器MyInterceptor中的postHandle,mv:"+mv);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("执行了拦截器MyInterceptor中的afterCompletion");
}
}
注册拦截器springmvc.xml
mvc:mapping 表示拦截请求,/**表示拦截所有请求
bean是注册监听器类,使用全限定名称。
<!--声明拦截器对象-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.bjpowernode.interceptor.MyInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
执行结果是:
执行了拦截器MyInterceptor中的preHandle
执行了处理器方法
执行了拦截器MyInterceptor中的postHandle
执行了拦截器MyInterceptor中的afterCompletion
多个拦截器
写多个拦截器类,都实现HandlerInterceptor,并实现preHandler、postHandler、afterCompletion方法。
注册拦截其对象(这里以两个拦截器为例)
有多个监听器,使用多个 mvc:interceptor声明。执行顺序根据声明的监听器顺序判定
<!--声明拦截器对象-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.bjpowernode.interceptor.MyInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.bjpowernode.interceptor.MyInterceptor1" />
</mvc:interceptor>
</mvc:interceptors>
两个拦截器可能的返回结果:
- 第一个拦截器preHandle=true , 第二个拦截器preHandle=true
执行了拦截器MyInterceptor-1111中的preHandle
执行了拦截器MyInterceptor-22222中的preHandle
使用doSome方法处理some.do的请求za|22
执行了拦截器MyInterceptor-22222中的postHandle
执行了拦截器MyInterceptor-1111中的postHandle
执行了拦截器MyInterceptor-22222中的afterCompletion
执行了拦截器MyInterceptor-1111中的afterCompletion
- 第一个拦截器preHandle=true , 第二个拦截器preHandle=false
执行了拦截器MyInterceptor-1111中的preHandle
执行了拦截器MyInterceptor-22222中的preHandle
执行了拦截器MyInterceptor-1111中的afterCompletion
- 第一个拦截器preHandle=false , 第二个拦截器preHandle=true|false
执行了拦截器MyInterceptor-1111中的preHandle
权限拦截器
在执行请求方法之前,先执行拦截器类的preHandler方法,判断返回true还是false。满足条件,返回true,继续执行处理器方法;不满足条件,返回false,不继续执行处理器方法