springmvc DispatcherServlet和拦截器详解

1,程序实例

把程序贴下来:web.xml

<servlet> <!--既然DispatcherServlet 写在这说明 DispatcherServlet也是servlet-->
    <servlet-name>mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:config/spring-mvc.xml</param-value>
    </init-param>
  </servlet>
<servlet-mapping>
    <servlet-name>mvc</servlet-name>
    <url-pattern>/</url-pattern>  <!-- 不可以用 /* 来代替所有的路径,这里拦截的是所有的路径,
故意的,一般不要这样写,而是要加上一些限制 -->
  </servlet-mapping>
<servlet>
    <servlet-name>ToLogin</servlet-name>
    <servlet-class>servlet.ToLogin</servlet-class>
  </servlet>
<servlet-mapping>
    <servlet-name>ToLogin</servlet-name>
    <url-pattern>/toLogin.do</url-pattern><!-- servlet的请求路径-->
</servlet-mapping>

config包中的 spring-mvc.xml文件的主要信息:

	<!-- 避免 Dispatcher 拦截掉静态资源,当静态资源路径出现时,交由DispatcherServlet
处理,不会找其他Controller ,而是交给 ResourceHttpRequestHandler 处理,从而找到静态资源-->
    <mvc:resources location="/page/" mapping="/page/**"/> 
<!--配置拦截器, 多个拦截器,顺序执行 ,路径拦截的相同也是互不影响的。-->  
<mvc:interceptors>    
    <mvc:interceptor>    
       
<!-- 匹配的是url路径, 如果不配置 或 /**,将拦截所有的Controller,这里为做实验,采取全拦截 -->
        <mvc:mapping path="/**" />  
        <bean class="interceptor.MyInterceptor"></bean>    
    </mvc:interceptor>  
  <!--  当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法-->  
</mvc:interceptors>

配置文件就这些。

接下来的就是Java代码:

ToLogin:路径是 /toLogin.do
public class ToLogin extends HttpServlet {

	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request,response);
	}

	@Override
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		 System.out.println("spring MVC 进入 ToLogin ");
		 request.getSession().setAttribute("name","ToLogin.do");
		 if(request.getCookies()!=null)
				for(Cookie c:request.getCookies()){
					System.out.println(c.getName()+" : "+c.getValue());
				}
		 request.getRequestDispatcher("/login.jsp").forward(request, response);
	}

}
MyInterceptor: 作用是拦截所有的请求Controller的路径。
public class MyInterceptor extends HandlerInterceptorAdapter {
	/* preHandle是一开始就 执行的 方法,并由返回的结果决定--> 后面的 拦截器是否执行 */
	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		System.out.println("preHandle 执行!!!");
		
		return false; // 为了说明效果,全部拦截下来
		
	}


	/* postHandle 是controller正常执行完成后,执行的方法。如果没有正常执行完成,所有的postHandle 方法都不会执行 */
	/* 该方法在controller正常执行完成之后 才会执行,并且在 中央处理器 渲染页面之前 执行。 */
	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("postHandle 执行!!!");
	}


	/* afterCompletion 是只要该拦截器的preHandle 方法执行的结果为true ,该方法就执行 */
	/*
	 * afterCompletion 在所有的工作完成之后,且该该拦截器的 preHandle 返回的结果是 true ,该方法相当于
	 * try-catch-finally 中的finally ,用来释放一些资源。
	 */
	@Override
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("afterCompletion 执行!!!");
	}
}
ControllerOne:代码 跳转到 index.jsp页面
@Controller
public class ControllerOne {
	// @RequestMapping("/hello") 这两种url的请求方式都是一样的。一种是绝对路径,一种是相对路径
	//
	@RequestMapping("hello")
	public ModelAndView getHello(int num) {
		System.out.println("进入hello请求中");
		ModelAndView mv = new ModelAndView();
		mv.setViewName("/index.jsp");
		return mv;
	}
}

请求结果及说明

本项目名为 springMVC 。
1,请求为 :http://localhost:8080/springMVC/login.jsp

结果如上,所加载的图片没有显示出来。查看控制台:

Mapped URL path [/page/**] onto handler 'org.springframework.web.servlet.resource.ResourceHttpRequestHandler'
说明配置文件中的信息,静态资源信息已经交给了ResourceHttpRequestHandler这个Controller处理,DispatcherServlet会将静态资源交由它处理。
preHandle 执行!!!
说明拦截器起了作用,而虽然请求login.jsp页面,但是有两次请求,一次是请求login.jsp第二次是请求 <img alt="你好" src="page/pieBiz.jpg"/> 静态资源,但是拦截器只拦截一次,且根据结果看,只是拦截了后面的静态资源的请求,导致没有加载出图画。原因也在上面的日志输出上显示出来了,就是为静态资源服务的ResourceHttpRequestHandler被拦截,从而不会被处理的原因。
下一个请求:
http://localhost:8080/springMVC/toLogin.do

其实控制台上没有出现报错或警告信息,这是为什么呢?毕竟是没有toLogin.do对应的Controller,那么DispatcherServlet如何将请求信息正确转发呢?其实这么想就错了。上面已经提到了DispatcherServlet本身就是一个转发的servlet,并根据路径的匹配原则,最长路径匹配优先匹配的原则,所以当碰到一个合适的servlet就会先执行该servlet,这里就是ToLogin.java, 同样原理,jsp就是特殊的servlet,所以会直接访问到,根本不经过
DispatcherServlet。
下面解决静态资源无法访问到的问题:
判断当前的处理器是否是:org.springframework.web.servlet.resource.ResourceHttpRequestHandler,如果是就说明这个请求其实是静态资源的请求。就要放行,改后的代码如下(拦截其中):
@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		System.out.println("preHandle 执行!!!");
		String str=handler.getClass().getName();
		//判断是否是静态资源的处理器,是就放行
		if("org.springframework.web.servlet.resource.ResourceHttpRequestHandler".equals(str)){
			return true;
		}
		return false;
		
	}


上图是资源的代码层级。
其中index.jsp 和 helloone.html文件都是普通的文件,只是展示一些东西。要详细说明的是 login.jsp :
<body>
    <form action="login" method="post">
        姓名:  <input type="text" name="name" /><br/>
        密码:  <input type="password" name="passwd" /><br/>
        <input type="submit" value="提交"/>
        <input type="reset" value="清空"/> 
    </form>
    <img alt="你好" src="page/pieBiz.jpg"/> //引用的静态资源
  </body>


运行结果如下(图片被显示出来):

通过这个例子相信大家已经对springMVC 的拦截器和DispatcherServlet以及servlet,jsp有了进一步的了解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值