注意,对于请求转发的页面,可以是WEB-INF中页面;而重定向的页面,是不能为WEB-INF中页面。因为重定向相当于用户再次发出一次请求,而用户是不能直接访问 WEB-INF 中资源的。
SpringMVC 框架把原来 Servlet 中的请求转发和重定向操作进行了封装。现在可以使用简单的方式实现转发和重定向。
表示转发,实现 request.getRequestDispatcher(“xx.jsp”).forward()
不和视图解析器一同工作,可以访问WEB-INF中的页面
setViewName("forward:视图文件完整路径")
@RequestMapping(value = "/doForward.do")
public ModelAndView doSome(){
//处理some.do请求了。 相当于service调用处理完成了。
ModelAndView mv = new ModelAndView();
mv.addObject("msg","欢迎使用springmvc做web开发");
mv.addObject("fun","执行的是doSome方法");
//使用forward显示转发
//mv.setViewName("forward:/WEB-INF/view/show.jsp");
mv.setViewName("forward:/hello.jsp");
return mv;
}
表示重定向,实现 response.sendRedirect(“xxx.jsp”)
不和视图解析器一同工作,不可以访问WEB-INF中的页面
setViewName("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 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/springmvc/hello.jsp?myname=lisi&myage=22
//重定向不能访问/WEB-INF资源
//mv.setViewName("redirect:/WEB-INF/view/show.jsp");
return mv;
}
1)@ControllerAdvice:定义在类上面,给控制器类增强异常处理功能,使用需要在springmvc配置文件中声明组件扫描器来指定该注解所在的包名。
2)@ExceptionHandler:定义在方法上面,里面value属性表示异常的类型,当发生此类异常则由当前方法处理异常。
public class MyUserException extends Exception{
public MyUserException() {
super();
}
public MyUserException(String message) {
super(message);
}
}
/**
* 表示用户姓名有异常,抛出异常
*/
public class NameException extends MyUserException {
public NameException() {
super();
}
public NameException(String message) {
super(message);
}
}
/**
* 表示年龄有异常抛出异常
*/
public class AgeException extends MyUserException{
public AgeException() {
super();
}
public AgeException(String message) {
super(message);
}
}
@ControllerAdvice
public class GlobalExceptionHandler {
//定义方法,处理异常
@ExceptionHandler(value = NameException.class)
public ModelAndView doNameException(Exception exception){
//处理NameException的异常
ModelAndView mv = new ModelAndView();
mv.addObject("msg","姓名必须是张三,其它用户不能访问");
mv.addObject("ex",exception);
mv.setViewName("nameError");
return mv;
}
@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;
}
//处理其它异常
@ExceptionHandler
public ModelAndView doOtherException(Exception exception){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","发生其它异常");
mv.addObject("ex",exception);
mv.setViewName("defaultError");
return mv;
}
}
<context:component-scan base-package="com.hcz.controller" />
<context:component-scan base-package="com.hcz.handler"/>
<mvc:annotation-driven/>
<body>
ageError.jsp<br/>
提示信息:${msg}<br>
系统异常信息:${ex.message}
body>
<body>
nameError.jsp<br/>
提示信息:${msg}<br>
系统异常信息:${ex.message}
body>
<body>
defaultError.jsp<br/>
提示信息:${msg}<br>
系统异常信息:${ex.message}
body>
1、定义类实现HandlerInterceptor接口
2、在springmvc配置文件中,声明拦截器, 让框架知道拦截器的存在。
1)在请求处理之前, 也就是controller类中的方法执行之前先被拦截。
2)在控制器方法执行之后也会执行拦截器。
3)在请求处理完成后也会执行拦截器。
preHandle返回true :请求是通过了拦截器的验证,可以执行处理器方法
拦截器的MyInterceptor的preHandle()
=执行MyController中的doSome方法=
拦截器的MyInterceptor的postHandle()
拦截器的MyInterceptor的afterCompletion()
preHandle返回false :请求没有通过拦截器的验证,请求到达拦截器就截止了, 请求没有被处理
特点:
1、方法在控制器方法(MyController的doSome)之前先执行的。用户的请求首先到达此方法
2、在这个方法中可以获取请求的信息, 验证请求是否符合要求。可以验证用户是否登录, 验证用户是否有权限访问某个连接地址(url)。
如果验证失败,可以截断请求,请求不能被处理。
如果验证成功,可以放行请求,此时控制器方法才能执行。
特点:
1、该方法在处理器方法执行之后执行。处理器方法若最终未被执行,则该方法不会执行。
2、该方法参数中包含 ModelAndView,所以该方法可以修改处理器方法的处理结果数据,且可以修改跳转方向
当 preHandle()方法返回 true 时,会将该方法放到专门的方法栈中,等到对请求进行响应的所有工作完成之后才执行该方法,一般做资源回收工作的,它是最后执行的方法。
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.hcz.handler.MyInterceptor" />
mvc:interceptor>
mvc:interceptors>
从图中可以看出,只要有一个 preHandle()方法返回 false,则上部的执行链将被断开,
其后续的处理器方法与 postHandle()方法将无法执行。但无论执行链执行情况怎样,只要方法栈中有方法,即执行链中只要有 preHandle()方法返回 true,就会执行方法栈中的 afterCompletion()方法,最终都会给出响应。
1、过滤器是servlet中的对象, 拦截器是框架中的对象;过滤器实现Filter接口的对象, 拦截器是实现HandlerInterceptor
2、过滤器是用来设置request,response的参数,属性的,侧重对数据过滤的;拦截器是用来验证请求的,能截断请求。
3、过滤器是在拦截器之前先执行的。
4、过滤器是tomcat服务器创建的对象;拦截器是springmvc容器中创建的对象
5、过滤器是一个执行时间点;拦截器有三个执行时间点
6、过滤器可以处理jsp,js,html等等;拦截器是侧重拦截对Controller的对象。 如果你的请求不能被中央调度器DispatcherServlet接收, 这个请求不会执行拦截器内容
7、拦截器拦截普通类方法执行,过滤器过滤servlet请求响应
实现步骤:
1、新建maven
2、修改web.xml注册中央调度器
3、新建index.jsp发起请求
4、创建MyController处理请求
5、创建结果show.jsp
6、创建一个login.jsp,模拟登录(把用户信息保存到session中)
7、创建一个logout.jsp,模拟退出系统(从session中删除数据)
8、创建拦截器,从session中获取用户的登录数据,验证是否访问系统
9、创建一个验证的jsp,如果验证视图,给出提示
10、创建springmvc配置文件
1) 声明组件扫描器
2) 声明拦截器
<body>
<p>一个拦截器p>
<form action="some.do" method="post">
姓名:<input type="text" name="name"> <br/>
年龄:<input type="text" name="age"> <br/>
<input type="submit" value="提交请求">
form>
body>
@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;
}
}
<body>
<h3>/WEB-INF/view/show.jsp从request作用域获取数据h3><br/>
<h3>myname数据:${myname}h3><br/>
<h3>myage数据:${myage}h3>
body>
<body>
模拟登录,zs登录系统
<%
session.setAttribute("name","zs");
%>
body>
<body>
退出系统
<%
session.removeAttribute("name");
%>
body>
/**
* 拦截器类:拦截用户的请求
*/
public class MyInterceptor implements HandlerInterceptor {
@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;
}
return true;
}
}
<body>
tips.jsp 非张三不能访问
body>
<context:component-scan base-package="com.hcz.controller" />
<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>
<mvc:mapping path="/**"/>
<bean class="com.hcz.handler.MyInterceptor" />
mvc:interceptor>
mvc:interceptors>
1)http://localhost:8080/springmvc/index.jsp
因为zs用户没有登录,所以不能响应index.jsp页面请求
2)http://localhost:8080/springmvc/login.jsp
3)http://localhost:8080/springmvc/index.jsp
因为zs用户已经登录,所以能响应index.jsp页面请求并转发到show.jsp页面
4)http://localhost:8080/springmvc/login.jsp
5)http://localhost:8080/springmvc/logout.jsp
6)http://localhost:8080/springmvc/index.jsp
当zs用户退出系统后也不能再响应index.jsp页面了