1 配置springmvc的注解时的事务[在controller中]不起作用问题
1.1 错误做法:
如果在applicationContext.xml中配置这样配置事务是不起作用的[在controller中还是service中 需要进步考究]
[在applicationContext.xml中配置]
<context:component-scan base-package="com.a.b"/>
<import resource="classpath:spring/spring-*.xml"/>
1.2 正确做法:
spring容器和springmvc容器是不同的容器,需要单独配置springmvc, 让controller只被springmvc容器管理
1.2.1 在applicationContext.xml中配置
<context:component-scan base-package=“com.a.b”>
<context:exclude-filter expression=“org.springframework.stereotype.Controller” type=“annotation” />
</context:component-scan>
1.2.2 在spring-mvc.xm中配置
<context:component-scan base-package="com.a.b.controller" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
1.2.3. 事务是加在controller还是service:
- 当然我们被教育应该加在处理业务的service,controller只是处理参数和很简单的处理
- 但是controller就不能加入事务了吗?见 事务加在controller
结论: 可以加,但需要在spring-mvc上要加入<tx:annotation-driven transaction-manager="txManager" />
,并且controller层中只支持@Trasnsactional注解
1.2.4 如果事务是加载service层,那么spring-mvc.xml中是不是就不需要配置<context:component-scan base-package="com.creative.controller" >
了
实例:
我们共有Spring和SpringMVC两个容器,它们的配置文件分别为applicationContext.xml和applicationContext-MVC.xml。
1.在applicationContext.xml中配置了<context:component-scan base-package=“com.hafiz.www" />,负责所有需要注册的Bean的扫描和注册工作。
2.在applicationContext-MVC.xml中配置<mvc:annotation-driven />,负责SpringMVC相关注解的使用。
3.启动项目我们发现SpringMVC无法进行跳转,将log的日志打印级别设置为DEBUG进行调试,发现SpringMVC容器中的请求好像没有映射到具体controller中。
4.在applicationContext-MVC.xml中配置<context:component-scan base-package=“com.hafiz.www" />,重启后,验证成功,springMVC跳转有效。
从SpringMVC的DispatcherServlet开始往下找,我们发现SpringMVC初始化时,会寻找SpringMVC容器中的所有使用了@Controller注解的Bean,来确定其是否是一个handler。1,2两步的配置使得当前springMVC容器中并没有/*因为默认AbstractHandlerMethodMapping.detectHandlerMethodsInAncestorContexts=false,即,mvc容器默认获取本容器的bean,而不包括父容器的bean*/
注册带有@Controller注解的Bean,而是把所有带有@Controller注解的Bean都注册在Spring这个父容器中了,所以springMVC找不到处理器,不能进行跳转。也就是说,把detectHandlerMethodsInAncestorContexts=true. mvc容器就可以获取父容器的bean了,
1.3 但但但==================== ==========================
官方推荐根据不同的业务模块来划分不同容器中注册不同类型的Bean:Spring父容器负责所有其他非@Controller注解的Bean的注册,而SpringMVC只负责@Controller注解的Bean的注册,使得他们各负其责、明确边界。
即如上配置 [1.2 正确做法]
2 利用properties文件进行多环境取值
1. 错误做法:
1. applicationContext.xml
<!-- Spring 自动注入 properties文件中 需要 configProperties propertyConfigurer -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:props/*.properties</value>
</list>
</property>
</bean>
2. a.properties
abc=${ABC}
3. filter-*.properties
filter-dev.properties
ABC=AABBCC
filter-production.properties
ABC=aabbcc
4. war工程的pom.xml
5. java代码中的调用
import org.springframework.beans.factory.annotation.Value;
@Controller
public class ATestController{
@Value("${abc}")
private String cameraRecognizeAlias;//dev -- AABBCC; production -- aabbcc
...
}
6. 补充
说明:
上述配法,在@Service中调用是可以的;但是在controller中调用是读不到filter-dev.properties中的值的,只能是${abc}。原因就是在controller中没能加载到a.properties,究其原因就是spring容器在扫描时除去了Controller
<context:component-scan base-package="com.a.b">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation" />
</context:component-scan>
所以需要在spring-mvc.xml中指定加载propertis.
即在前边五步后,还需在spring-mvc.xm中配置
在spring-mvc.xm中配置
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:props/*.properties</value>
</list>
</property>
</bean>
到此结束。就为了这一个配置浪费了很多时间!!!