转发和重定向
在控制器内部处理请求的方法中,默认返回字符串时的处理方式是转发,转发的值是view组件的名称,比如return "login",实质上会根据视图解析器(ViewResolver)得到最终负责显示的页面,而通过return redirect:路径这样的语法表示重定向,在redirect:右侧的内容是路径,这个路径通常使用相对的路径,是以当前客户端的地址栏中的路径为标准进行参考,
例如当前的地址为:http://localhost:8080/Project/user/reg,然后return "redirect:login",则会重定向到http://localhost:8080/Project/user/login,
如果return "redirect:/main/index"或者return "redirect:../main/index",则会重定向到http://localhost:8080/Project/main/index
forward:
不添加任何字段,那么spring中默认的是转发,比如return login,那么这个会经过视图解析器进行解析,跳转到指定的视图。但是如果添加了forward,那么就不经过视图解析器,而是直接进行跳转,我们一般都是转发到controller中的方法,比如return forward:../user/showLogin.do
redirect:
重定向 : return "redirect:login.do"
返回的是一个Controller方法的路径,而不是一个view,这个不会经过视图解析器,而是直接跳转
实例:
@RequestMapping(value = "login")
public String login(String name,String pwd,Model model,HttpSession session) {
if (name.equals("srd")&&pwd.equals("123")) {
session.setAttribute("name", name);
return "redirect:/main"; //重定向到main这个控制方法,main对应的就是转发到main.jsp
}else {
model.addAttribute("mes", "账号密码错误");
return "login";
}
}
@RequestMapping(value = "main")
public String toMain() {
return "main";
}
@RequestMapping(value = "loginOut")
public String loginOut(HttpSession session) {
session.invalidate();//session失效
return "login";
}
拦截器的定义
在 Spring MVC 框架中定义一个拦截器需要对拦截器进行定义和配置,定义一个拦截器可以通过两种方式:
一种是通过实现 HandlerInterceptor 接口或继承 HandlerInterceptor 接口的实现类来定义;
另一种是通过实现 WebRequestInterceptor 接口或继承 WebRequestInterceptor 接口的实现类来定义。实现 HandlerInterceptor 接口的定义方式自定义拦截器()的使用方法。示例代码如下:
public class TestInterceptor1 implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("拦截器1,视图渲染之后执行>>>>");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("拦截器1,业务逻辑执行之后,视图渲染之前执行>>>>");
}
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
// TODO Auto-generated method stub
System.out.println("拦截器1,拦截请求之后,业务逻辑执行之前执行此方法>>>>>");
return true;
}
}
在上述拦截器的定义中实现了 HandlerInterceptor 接口,并实现了接口中的 3 个方法。
preHandle 方法:该方法在控制器的处理请求方法前执行,其返回值表示是否中断后续操作,返回 true 表示继续向下执行,返回 false 表示中断后续操作。
postHandle 方法:该方法在控制器的处理请求方法调用之后、解析视图之前执行,可以通过此方法对请求域中的模型和视图做进一步的修改。
afterCompletion 方法:该方法在控制器的处理请求方法执行完成后执行,即视图渲染结束后执行,可以通过此方法实现一些资源清理、记录日志信息等工作。
拦截器的配置
让自定义的拦截器生效需要在 Spring MVC 的配置文件中进行配置,配置示例代码如下:
<!-- 配置拦截器 -->
<mvc:interceptors>
<!-- 配置一个全局拦截器,拦截所有请求 -->
<bean class="interceptor.TestInterceptor" />
<mvc:interceptor>
<!-- 配置拦截器作用的路径 -->
<mvc:mapping path="/**" />
<!-- 配置不需要拦截作用的路径 -->
<mvc:exclude-mapping path="##" />
<!-- 定义<mvc:interceptor>元素中,表示匹配指定路径的请求才进行拦截 -->
<bean id="testInterceptor1" class="com.srd.interceptor.TestInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<!-- 配置拦截器作用的路径 -->
<mvc:mapping path="/Test2" />
<!-- 定义在<mvc: interceptor>元素中,表示匹配指定路径的请求才进行拦截 -->
<bean id="testInterceptor2" class="com.srd.interceptor.TestInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
在上述示例代码中,<mvc:interceptors> 元素用于配置一组拦截器,其子元素 <bean> 定义的是全局拦截器,即拦截所有的请求。
<mvc:interceptor> 元素中定义的是指定路径的拦截器,其子元素 <mvc:mapping> 用于配置拦截器作用的路径,该路径在其属性 path 中定义。
如上述示例代码中,path 的属性值“/**”表示拦截所有路径,“/gotoTest”表示拦截所有以“/gotoTest”结尾的路径。如果在请求路径中包含不需要拦截的内容,可以通过 <mvc:exclude-mapping> 子元素进行配置。
需要注意的是,<mvc:interceptor> 元素的子元素必须按照 <mvc:mapping.../>、<mvc:exclude-mapping.../>、<bean.../> 的顺序配置。
演示登录检查
登录检查: 当涉及到用户信息的修改,查看什么的,必须要验证是否登录,因此需要设计拦截器验证登录
先设定登录数据,即: 在login.jsp中添加登录按钮,登录完成之后,需要自己定义一个标记存储在session中,比如用户的id或者用户的对象
我们使用用户的id作为标记验证是否已经的登录,如果用户登录成功,会在session中添加一个uid的属性
用户退出登录使用session.invalidate();清除session,并且重定向到登录界面
自定义拦截器(LoginInterceptor)
public class LoginInterceptor implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub
}
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object obj) throws Exception {
// TODO Auto-generated method stub
String news=req.getRequestURI();
//如果存在,那么即可登录完成
if (news.indexOf("toLogin")>=0||news.indexOf("login")>=0) {
return true;//返回true,登录成功就需要执行后续的流程
}
Object object= req.getSession().getAttribute("name");
if (object!=null) {
return true;//返回true,登录成功就需要执行后续的流程
}else {
req.setAttribute("mes", "请先登录!!!");
req.getRequestDispatcher("login.jsp").forward(req, res);
return false;//返回false,后面的流程也不用执行了,直接中断
}
}
}
springmvc中配置拦截器
由于这里只是跳转到用户中心需要验证登录,那么只是匹配了login
<!-- 配置拦截器,拦截全部,放行登录login路径-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/login"/>
<bean id="LoginInterceptor" class="com.srd.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
多个拦截器的执行顺序
根据在springmvc配置文件中配置的顺序执行,即是在<mvc:interceptors>下配置的拦截器的顺序,如果对同一个路径进行了拦截器,那么先配置的先拦截
拦截器和过滤器的区别(主要的区别)
拦截器是springmvc中,仅仅当使用springmvc才可以使用拦截器,过滤器是Java EE体系中的,无论使用哪种框架都可以使用过滤器
拦截器在DispatcherServlet之后,在处理器之前执行,过滤器在DispatcherServlet之前执行
过滤器会在所有的servlet之前执行(所有的请求都会执行),而拦截器会在springmvc中DispatcherServlet之后执行,所以过滤器在项目中可以过滤任何请求(只要是配置了对应的路径),而拦截器只会在DispatcherServlet处理的请求的基础之上进行拦截。