sping mvc 简单配置及原理

spring要怎么配置呢,为什么这么配置呢,我一直想不明白。对于这些,我找了很久,总算明白一点,现在记录下来,留待以后查阅。

1. 注解配置

  现在基本上都是注解配置了,很简单。就是因为太简单了所有理解不了。为什么这么配置呢?这个疑问会在下面讲解。

  这一步只是讲,spring要怎么配置。

  1.1 先配置web.xml ,这里的作用就是:怎样的请求会被spring处理

  <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>*.html</url-pattern>
  </servlet-mapping>

这里配置的意思是,以 .html 结尾的请求都会被spring处理

  1.2   配置 /WEB-INF/spring-servlet.xml , 这里的作用就是告诉spring要怎么去处理这些请求。这里有个注意点就是spring的配置文件的命名问题。我们采用的是默认命名方式:<servlet-name>-servlet.xml;<servlet-name>就是在web.xml里面配置的servlet的名字。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="
     http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context.xsd
     http://www.springframework.org/schema/mvc
     http://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<context:component-scan base-package="com.wyy.learn"/>
	
	<!-- HanddlerMapping HanddlerAdapter -->
	<mvc:annotation-driven />

	<!-- ViewResolver -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
		<property name="prefix" value="/WEB-INF/jsp/"/>
		<property name="suffix" value=".jsp"/>
	</bean>

</beans>

  1.3 下面是一个简单的java例子

package com.wyy.learn;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class testControl{
	private static final Logger LOGGER = LogManager.getLogger("testlogger");

	@RequestMapping("/hello.html")
	public ModelAndView handleRequest(HttpServletRequest arg0,
			HttpServletResponse arg1) throws Exception {
		
		ModelAndView mv = new ModelAndView();
		
		mv.addObject("message", "Hello world xml");
		
		mv.setViewName("index");
		
		return mv;
	}
}

  1.4  这里还需要一个相对应的jsp页面, /WEB-INF/jsp/index.jsp

      这个页面的路径和命名也是有要求的:先看路径,在spring-servlet.xml文件里面,我们定义了一个ViewResolver(视图解析器)。prefix 定义了路径,suffix 定义了文件的后缀名。再来看看文件的命名:我们在java代码里面有一个返回的视图名:mv.setViewName("index"), 这里的index就是文件名了。

好了,一个简单的spring配置就OK了。

2. 为什么这么配置呢?先来看下第二种配置方式,继承controller接口的实现方式.

  2.1 web.xml

  <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>*.html</url-pattern>
  </servlet-mapping>

  2.2  /WEB-INF/spring-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="
     http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context.xsd
     http://www.springframework.org/schema/mvc
     http://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<!-- HanddlerMapping -->
	<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
	
	<!-- HanddlerAdapter -->
	<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
	
	<!-- handdler -->
	<bean name="/hello.html" class="com.wyy.learn.testControl"/>
	
	<!-- ViewResolver -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
		<property name="prefix" value="/WEB-INF/jsp/"/>
		<property name="suffix" value=".jsp"/>
	</bean>

</beans>

   2.3 java代码

package com.wyy.learn;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class testControl implements Controller{
	private static final Logger LOGGER = LogManager.getLogger("testlogger");

	@Override
	public ModelAndView handleRequest(HttpServletRequest arg0,
			HttpServletResponse arg1) throws Exception {
		
		ModelAndView mv = new ModelAndView();
		
		mv.addObject("message", "Hello world xml");
		
		mv.setViewName("index");
		
		return mv;
	}
}


结论:

现在说下我对这两个配置的理解:

  1. @Controller  是代替 Controller 接口的。

  2. <context:component-scan base-package="com.wyy.learn"/> 和 @RequestMapping("/hello.html")

    是代替 <bean name="/hello.html" class="com.wyy.learn.testControl"/>

  3. <mvc:annotation-driven /> 是代替<!-- HanddlerMapping --> 和 <!-- HanddlerAdapter --> 的

这些配置的对应关系都已经清楚了,但为什么这么配置呢?先看下日志输出,从日志里面可以看到spring的处理过程,通过这个过程,我们就能理解,为什么这么配置了。

先看下第二种配置情况的日志

2015-08-05 09:39:27,872 TRACE (FrameworkServlet.java:1052) - Bound request context to thread: org.apache.catalina.connector.RequestFacade@e174f70
2015-08-05 09:39:27,872 DEBUG (DispatcherServlet.java:861) - DispatcherServlet with name 'spring' processing GET request for [/springTest/hello.html]
2015-08-05 09:39:27,875 TRACE (DispatcherServlet.java:1117) - Testing handler map [org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping@73e3862b] in DispatcherServlet with name 'spring'
2015-08-05 09:39:27,879 DEBUG (AbstractUrlHandlerMapping.java:141) - Mapping [/hello.html] to HandlerExecutionChain with handler [com.wyy.learn.testControl@1020c592] and 1 interceptor
2015-08-05 09:39:27,880 TRACE (DispatcherServlet.java:1157) - Testing handler adapter [org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter@11d9ebba]
2015-08-05 09:39:27,881 DEBUG (DispatcherServlet.java:947) - Last-Modified value for [/springTest/hello.html] is: -1
2015-08-05 09:39:27,884 DEBUG (AbstractAutowireCapableBeanFactory.java:1620) - Invoking afterPropertiesSet() on bean with name 'index'
2015-08-05 09:39:27,884 TRACE (AbstractCachingViewResolver.java:164) - Cached view [index]
2015-08-05 09:39:27,884 DEBUG (DispatcherServlet.java:1241) - Rendering view [org.springframework.web.servlet.view.JstlView: name 'index'; URL [/WEB-INF/jsp/index.jsp]] in DispatcherServlet with name 'spring'
2015-08-05 09:39:27,884 TRACE (AbstractView.java:297) - Rendering view with name 'index' with model {message=Hello world xml} and static attributes {}
2015-08-05 09:39:27,884 DEBUG (AbstractView.java:432) - Added model object 'message' of type [java.lang.String] to request in view with name 'index'
2015-08-05 09:39:27,892 DEBUG (InternalResourceView.java:166) - Forwarding to resource [/WEB-INF/jsp/index.jsp] in InternalResourceView 'index'
2015-08-05 09:39:27,944 TRACE (FrameworkServlet.java:1062) - Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@e174f70
2015-08-05 09:39:27,945 DEBUG (FrameworkServlet.java:1000) - Successfully completed request
2015-08-05 09:39:27,945 TRACE (AbstractApplicationContext.java:360) - Publishing event in WebApplicationContext for namespace 'spring-servlet': ServletRequestHandledEvent: url=[/springTest/hello.html]; client=[0:0:0:0:0:0:0:1]; method=[GET]; servlet=[spring]; session=[8F56AD205EF3D2B1BEBAE1F01D5E8F99]; user=[null]; time=[79ms]; status=[OK]

我们来分析下这个日志:

  1.  DispatcherServlet 拦截 [/springTest/hello.html] 请求

  2. 通过映射器 BeanNameUrlHandlerMapping 匹配映射链,[com.wyy.learn.testControl@1020c592] and 1 interceptor

  3. 通过适配器 SimpleControllerHandlerAdapter 调用处理器 testControl

  4. 通过解析器 渲染视图 Rendering view

  5. 跳转页面 Forwarding to resource [/WEB-INF/jsp/index.jsp] in InternalResourceView 'index'

通过这个日志,我总算知道了,为什么这么配置了。其实也一套就是 Spring  DispatcherServlet 的原理了。

再来看看第一种配置情况的日志

2015-08-05 10:02:23,469 TRACE (DispatcherServlet.java:1117) - Testing handler map [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping@42479576] in DispatcherServlet with name 'spring'
2015-08-05 10:02:23,476 TRACE (DispatcherServlet.java:1157) - Testing handler adapter [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter@45c6c4cf]

由于字数限制,只看这两句就好了. 从这里可以看出 <!-- HanddlerMapping --> 和 <!-- HanddlerAdapter -->

所以第一种配置里面可以这么改

	<!-- HanddlerMapping HanddlerAdapter -->
<!-- 	<mvc:annotation-driven /> -->

	<!-- HanddlerMapping -->
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
	
	<!-- HanddlerAdapter -->
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />


你可能感兴趣的:(sping mvc 简单配置及原理)