这是我的上一篇,没看过的可以在这里点击阅读 https://www.jianshu.com/p/00b5633b8477
上一篇是配置web.xml,最核心的配置就是DispatcherServlet。
里面的contextConfigLocation,读取的就是项目中spring包里的xml配置。
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</init-param>
有什么配置呢,我们来一探究竟。
从外到内,分别是spring-web.xml、spring-service.xml、spring-dao.xml
spring-web.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-3.0.xsd">
<!-- 配置SpringMVC -->
<!-- 1.开启SpringMVC注解模式 -->
<!-- 简化配置:
(1)自动注册DefaultAnootationHandlerMapping,AnotationMethodHandlerAdapter
(2)提供一些列:数据绑定,数字和日期的format @NumberFormat, @DateTimeFormat, xml,json默认读写支持
-->
<mvc:annotation-driven />
<!-- 2.静态资源默认servlet配置
(1)加入对静态资源的处理:js,gif,png
(2)允许使用"/"做整体映射
-->
<mvc:default-servlet-handler/>
<!-- 3.配置jsp 显示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>
<!-- 4.扫描web相关的bean -->
<context:component-scan base-package="com.cyh.controller" />
</beans>
spring-web.xml里面的核心配置是InternalResourceViewResolver,目的是配置viewClass,prefix,suffix。
而配置了以后,又如何会使用到了,这就回到了DispatcherServlet了。
众所周知,DispatcherServlet.doService方法是核心方法,我们来一看究竟。
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
//记日志
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
//加载“org.springframework.web.servlet”里面的属性
// Make framework objects available to handlers and view objects.
//request.setAttribute
try {
doDispatch(request, response);//这里就是正题了
}
}
来看看doDispatch方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
// Process last-modified header, if supported by the handler.
// Actually invoke the handler.
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
}
processDispatchResult方法里面的render方法
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
}
render方法里面的resolveViewName
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
View view;
if (mv.isReference()) {
// We need to resolve the view name.
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
"' in servlet with name '" + getServletName() + "'");
}
}
}
然后,就跟到org.springframework.web.servlet.view.AbstractCachingViewResolver.resolveViewName(String, Locale),里面的createView方法,然后跟到org.springframework.web.servlet.view.UrlBasedViewResolver.loadView(String, Locale),最终跟到org.springframework.web.servlet.view.InternalResourceViewResolver.buildView(String),buildView这个方法,会把viewClass、prefix、suffix等属性加载起来。
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
InternalResourceView view = (InternalResourceView) super.buildView(viewName);
if (this.alwaysInclude != null) {
view.setAlwaysInclude(this.alwaysInclude);
}
view.setPreventDispatchLoop(true);
return view;
}
spring-service.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:tx="http://www.springframework.org/schema/tx"
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/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 扫描service包下所有使用注解的类型 -->
<context:component-scan base-package="com.cyh.service.impl" />
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置基于注解的声明式事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
我们来看看spring-service,transactionManager是事务管理器,事务在mvc中是拦截器中拦截的,主要控制的是方法,于是跟源码跟到org.springframework.transaction.interceptor.TransactionInterceptor.invoke(MethodInvocation)方法,这个方法中的invokeWithinTransaction方法,使用AOP Alliance MethodInterceptor 做事务管理。
spring-dao.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"
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">
<!-- 配置整合mybatis过程 -->
<!-- 1.配置数据库相关参数properties的属性:${url} -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 2.数据库连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 配置连接池属性 -->
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!-- c3p0连接池的私有属性 -->
<property name="maxPoolSize" value="30" />
<property name="minPoolSize" value="10" />
<!-- 关闭连接后不自动commit -->
<property name="autoCommitOnClose" value="false" />
<!-- 获取连接超时时间 -->
<property name="checkoutTimeout" value="10000" />
<!-- 当获取连接失败重试次数 -->
<property name="acquireRetryAttempts" value="2" />
</bean>
<!-- 3.配置SqlSessionFactory对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource" />
<!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
<property name="configLocation" value="classpath:mybatis-config.xml" />
<!-- 扫描entity包 使用别名 -->
<property name="typeAliasesPackage" value="com.cyh.entity" />
<!-- 扫描sql配置文件:mapper需要的xml文件 -->
<property name="mapperLocations" value="classpath:mapper/*.xml" />
</bean>
<!-- 4.配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入sqlSessionFactory -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
<!-- 给出需要扫描Dao接口包 -->
<property name="basePackage" value="com.cyh.dao.impl" />
</bean>
</beans>
spring-dao,我们看dataSource是在org.mybatis.spring.SqlSessionFactoryBean中作为属性的,那跟源码跟到,最终也是org.springframework.web.servlet.DispatcherServlet.doDispatch(ModelAndView, HttpServletRequest, HttpServletResponse)方法中,大概跟踪路径是跟spring-web是差不多的路径。
那么,我们是大概了解了,web.xml配置servlet,而属性配置基本就在DispatcherServlet.doDispatch中进行了配置,事务管理是在TransactionInterceptor.invoke中进行管理,那么,后续我们自定义扩展,就可以在这两个方法中进行了!