维护一个用Spring MVC 4.3.9.RELEASE(不是Spring Boot)编写的代码库......
在src / main / resources下:
有两种不同的数据库配置文件:
sampledb.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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Initialization for data source dbcp -->
<bean id="sampleDatabase" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
<property name="url"><value>jdbc:mysql://localhost/sampledb?zeroDateTimeBehavior=convertToNull</value></property>
<property name="username"><value>root/value></property>
<property name="password"><value></value></property>
<property name="maxIdle" value="10"/>
<property name="maxActive" value="50"/>
<property name="maxWait" value="100"/>
<property name="defaultAutoCommit" value="false"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="1"/>
<property name="minIdle" value="0"></property>
<property name="timeBetweenEvictionRunsMillis" value="1000"></property>
<property name="minEvictableIdleTimeMillis" value="1000"></property>
</bean>
</beans>
eventsdb.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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Initialization for data source dbcp -->
<bean id="eventsDatabase" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
<property name="url"><value>jdbc:mysql://localhost/eventsdb?zeroDateTimeBehavior=convertToNull</value></property>
<property name="username"><value>root</value></property>
<property name="password"><value></value></property>
<property name="maxIdle" value="10"/>
<property name="maxActive" value="50"/>
<property name="maxWait" value="100"/>
<property name="defaultAutoCommit" value="false"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="1"/>
<property name="minIdle" value="0"></property>
<property name="timeBetweenEvictionRunsMillis" value="1000"></property>
<property name="minEvictableIdleTimeMillis" value="1000"></property>
</bean>
</beans>
WEB-INF / web.xml中:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>MyApp</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
WEB-INF / MVC-调度-servlet.xml中:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
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
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<context:component-scan base-package="com.myapp.rest.controllers" />
<mvc:annotation-driven />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
示例网络服务代码:
package com.myapp.rest.controllers;
@Controller
@RequestMapping("/v2")
public class MyController {
@RequestMapping(value="users/{userId}",method=RequestMethod.GET)
public @ResponseBody Object getUserDetails(@PathVariable String userId){
Object response=null;
UserDAO dao = UserDAO.getInstance();
response=dao.getUser(userId);
return response;
}
}
userDAO的:
public class UserDAO {
private static UserDAO instance = null;
private JdbcTemplate jdbcTemplateObject = null;
public static UserDAO getInstance() {
if(instance == null) {
synchronized(UserDAO.class) {
if(instance == null) {
instance = new UserDAO();
}
}
}
return instance ;
}
UserDAO() {
try {
initializeDB();
}
catch(Exception e) {
e.printStackTrace();
}
}
private void initializeDB() {
try {
ApplicationContext context = new ClassPathXmlApplicationContext("sampledb.xml");
DataSource dataSource = (DataSource) context.getBean("sampleDatabase");
this.jdbcTemplateObject = new JdbcTemplate(dataSource);
}
catch (Exception e) {
e.printStackTrace();
}
}
// others methods which do the actual queries using Spring JDBC
}
前一作者在每个DAO中使用了这种模式(使用ApplicationContext初始化数据库)(代码库中有20个不同的模式,每个DAO使用相同的两个数据库配置文件执行相同的操作)!
问题(S):
这看起来非常不合适(好像应该做一次),如果war文件加载到Tomcat中,怎么能这样做(加载基于Spring的数据库配置文件)?
什么是性能提升的最佳技术(例如,我应该使用缓存系统还是数据库连接池)?
非常感谢任何建议......
答案 0 :(得分:1)
private void initializeDB() {
try {
ApplicationContext context = new ClassPathXmlApplicationContext("sampledb.xml");
DataSource dataSource = (DataSource) context.getBean("sampleDatabase");
this.jdbcTemplateObject = new JdbcTemplate(dataSource);
}
catch (Exception e) {
e.printStackTrace();
}
}
此代码非常危险,根据您的上下文大小,您最终会遇到问题。这里发生的是你在每次需要一个对象时加载整个应用程序,你将打开与db的连接(由于连接太多而最终会停止工作)你会遇到奇怪的事务问题并且可能(取决于大小) )记忆问题。 (当然,如果这是你想要的一切,那就这样继续)。
相反,你应该使用依赖注入。将所有需要的依赖项声明为字段,让spring执行自动连接,这将在启动时发生一次。
@Controller
@RequestMapping("/v2")
public class MyController {
private final UserDAO dao;
@Autowired
public MyController(UserDAO Dao) {
this.dao=dao;
}
@RequestMapping(value="users/{userId}",method=RequestMethod.GET)
public @ResponseBody Object getUserDetails(@PathVariable String userId){
return dao.getUser(userId);;
}
}
在你的UserDAO
做类似的事情。
@Repository
public class UserDAO {
private final JdbcTemplate jdbcTemplate;
@Autowired
public UserDAO(@Qualifier("sampleDatabase") DataSource dataSource) {
this.jdbcTemplate=new JdbcTemplate(dataSource);
}
// others methods which do the actual queries using Spring JDBC
}
另一件事是web.xml
你的ContextLoaderListener
和DispatcherServlet
。现在这不是一个问题,但在你的情况下,两个类都加载相同的应用程序上下文,导致你的应用程序被加载两次,一个实例什么都不做。
从ContextLoaderListener
删除context-param
和web.xml
。
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>MyApp</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
现在在mvc-dispatcher-servlet.xml
添加以下两行。
<import resource="classpath:sampledb.xml" />
<import resource="classpath:eventsdb.xml" />
或将两个文件的内容移至mvc-dispatcher-servlet.xml
。
答案 1 :(得分:0)
您可以使用JNDI配置作为App和Tomcat之间的最佳实践:
在您的xml配置中:
<jee:jndi-lookup id="sampleDatabase" jndi-name="jdbc/sampleDatabase" />
<bean id="sampleDatabaseJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="sampleDatabase" />
<property name="resultsMapCaseInsensitive" value="true" />
<property name="nativeJdbcExtractor" ref="nativeJdbcExtractor" />
</bean>
在tomcat server.xml上,您可以在<GlobalNamingResources>
<Resource name="jdbc/sampleDatabase" auth="Container" global="jdbc/sampleDatabase" type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/sampledb"
username="root" password="" maxActive="50" maxWait="-1" maxIdle="10"
validationQuery="SELECT 1 FROM DUAL" testOnBorrow="TRUE" />
on tomcat context.xml:
<ResourceLink auth="Container" global="jdbc/sampleDatabase" name="jdbc/sampleDatabase" type="javax.sql.DataSource"/>
以及您的UserDAO:
.....
@Autowired
@Qualifier("sampleDatabaseJdbcTemplate")
private JdbcTemplate sampleDatabaseJdbcTemplate;
...
您可以为第二个数据库执行相同的配置