下面将介绍使用spring+mybatis的开发样例:
首先,笔者创建的是一个maven工程,在开发先先导入相关的依赖jar:
pom.xml:
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- spring3 相关依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>3.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>3.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>3.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>3.0.5.RELEASE</version> </dependency> <!-- spring MVC --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>3.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>3.0.5.RELEASE</version> </dependency> <!-- mysql jdbc driver --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.13</version> </dependency> <!-- log 日志 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.2</version> </dependency> <!-- mybatis-spring 插件 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.1</version> </dependency> <!-- mybatis依赖 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.1</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- 数据库连接池 --> <dependency> <groupId>proxool</groupId> <artifactId>proxool</artifactId> <version>0.9.1</version> </dependency> <dependency> <groupId>proxool</groupId> <artifactId>proxool-cglib</artifactId> <version>0.9.1</version> </dependency> <!-- servlet-jsp 依赖,为编译jsp时使用 --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> </dependencies>
web.xml中对spring和数据库连接池的配置:
<context-param> <param-name>log4jConfigLocation</param-name> <param-value>/WEB-INF/log4j.xml</param-value> </context-param> <context-param> <param-name>log4jRefreshInterval</param-name> <param-value>60000</param-value> </context-param> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <!-- needed for ContextLoaderListener --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <!-- Bootstraps the root web application context before servlet initialization --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- The front controller of this Spring Web application, responsible for handling all application requests --> <servlet> <servlet-name>spring3</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <!-- Map all requests to the DispatcherServlet for handling --> <servlet-mapping> <servlet-name>spring3</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- database proxool config --> <servlet> <servlet-name>ServletConfigurator</servlet-name> <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class> <init-param> <param-name>xmlFile</param-name> <param-value>WEB-INF/proxool.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
在这里要注意,因为我使用了数据库连接池proxool,虽然已经设置servlet的启动级别是1,但是由于在servlet启动之前,spring(ContextLoaderListener)监听器已启动了,所以在spring监听启动时它会报一个找不到对应的数据源的SQLException。对于这个问题,本可以通过更改spring为servlet启动,并将启动级别设置为proxool配置加载之后解决:
<servlet> <servlet-name>contextConfigLocation</servlet-name> <servlet-class> org.springframework.web.context.ContextLoaderServlet </servlet-class> <load-on-startup>2</load-on-startup> </servlet>
但是因为spring3以后就不支持使用servlet启动了,官方推荐使用listener启动applicationContext。所以这个方法在新版本不适合了,不过这个异常可以忽略,因为proxool在整个项目加载完成的时候的确以及完成了加载,所以在项目运行起来以后是不会报错的,开始报错是spring做的一个检查。
为了解决乱码问题最好在web.xml中加上这个配置:
<!-- character filter. use UTF8 --> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
下面是对spring3-servlet.xml的配置,它里面申明的bean都存放在webApplicationContext中:
<?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:mvc="http://www.springframework.org/schema/mvc" default-lazy-init="false" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 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"> <context:component-scan base-package="com.pinche.statistic.web"></context:component-scan> <!-- 启用spring mvc注解 --> <mvc:annotation-driven /> <!-- 静态资源访问问题 --> <mvc:default-servlet-handler /> <!-- Default 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/page/"></property> <property name="suffix" value=".jsp"></property> </bean> <!-- 对抛给spring的异常的处理 --> <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="java.lang.Exception">error</prop> </props> </property> </bean> </beans>
下面对applicationContext.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:p="http://www.springframework.org/schema/p" 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-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- 数据源配置:这里配置了两个数据源dataSource_statistic和dataSource_pinche, 分别注入到_sqlSessionFactory_statistic和_sqlSessionFactory_pinche --> <bean id="dataSource_statistic" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <!-- 数据库连接 --> <property name="url" value="proxool.statistic" /> <!-- 这是不使用数据库连接池的配置方式,由于proxool只有在启动web应用的时候才能加载, 所以如果在初期开发阶段可以用这种简单的数据库连接方式,在通过 new FileSystemXmlApplicationContext("src/main/webapp/WEB-INF/applicationContext.xml") 获取到context,并进行测试。 <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://192.168.1.168:3306/statistic"/> <property name="username" value="statistic"></property> <property name="password" value="statistic"></property> --> </bean> <bean id="dataSource_pinche" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <!-- 数据库连接 --> <property name="url" value="proxool.pinche" /> </bean> <!-- 为mybatis-spring注入数据源 --> <bean name="_sqlSessionFactory_statistic" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注入数据源 --> <property name="dataSource" ref="dataSource_statistic"></property> <!-- 注入别名的包名前缀,这样就可以在mybatis的文件中直接写类名不用写全名了 --> <property name="typeAliasesPackage" value="com.pinche.statistic.domain" /> </bean> <bean name="_sqlSessionFactory_pinche" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注入数据源 --> <property name="dataSource" ref="dataSource_pinche"></property> <!-- 注入别名的包名前缀,这样就可以在mybatis的文件中直接写类名不用写全名了 --> <property name="typeAliasesPackage" value="com.pinche.statistic.domain" /> <!-- 该配置文件用来指定Mapper映射文件的位置 ,如果映射文件与相应的接口同名,且在同一路径下,那么可以不配置该选项--> <!--<property name="mapperLocations" value="src/UserMapper.xml"/>--> <!-- 该属性用来指定MyBatis的XML配置文件路径,跟Spring整合时, 编写MyBatis映射文件的目的无非是配置一下typeAlias、setting之类的 元素。不用在其中指定数据源,或者事务处理方式。就算配置了也会被忽略。 因为这些都是使用Spring中的配置。当然如果你不打算添加typeAlias 之 类的设置的话,你连MyBatis的配置文件都不用写,更不用配置这个属性了 --> <!-- <property name="configLocation" value=""/> --> </bean> <!-- 注册Mapper方式一 <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.pinche.statistic.mapper.ApplicationsMapper"/> <property name="sqlSessionFactory" ref="_sqlSessionFactory_statistic"/> </bean> --> <!-- 注册Mapper方式二:也可不指定特定mapper,而使用自动扫描包的方式来注册各种Mapper ,配置如下:--> <!-- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.pinche.statistic.mapper"></property> </bean> --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.pinche.statistic.dialstatistic.mapper"></property> <property name="sqlSessionFactoryBeanName" value="_sqlSessionFactory_pinche"></property> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.pinche.statistic.mapper"></property> <property name="sqlSessionFactoryBeanName" value="_sqlSessionFactory_statistic"></property> </bean> <!-- 事务 --> <!-- 虽然mybatis也有自己的事务配置,但是配置了也没用,事务最终会交由spring控制, 由于项目没有用到可以注掉。 --> <!-- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource_statistic" /> </bean> <tx:annotation-driven transaction-manager="transactionManager"/> --> <!-- 启用注解 --> <context:annotation-config /> <!-- 自动扫描注入 --> <context:component-scan base-package="com.pinche.statistic.dao, com.pinche.statistic.service" /> </beans>
Application.java是下面会用到的一个实体bean:
public class Application { public static final int APP_DISABLE = 0; public static final int APP_ENABLE = 1; private Integer id; private String appAccount;//每个app对应一个账户标识;对应生成的数据表 private String appName; private String appICON; private String appDesc; private String appURL; private Date createTime; private int isDisable;//'是否前台显示:0显示,1不显示' }
首先我们要编写一个与mapper.xml文件映射的接口文件,mybatis会将这个接口文件和对应的mapper文件中的sql语句关联,自动实现这个接口文件。在之后的开发中我们直接调用这个接口文件就可以了,因为内存中已经有接口相对应的实例了。
ApplicationsMapper.xml文件:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.pinche.statistic.mapper.ApplicationsMapper"> <insert id="add" parameterType="Application" useGeneratedKeys="true" keyProperty="id"> INSERT INTO applications (appName,appAccount,appICON,appDesc,appURL,createTime) VALUES (#{appName},#{appAccount},#{appICON},#{appDesc},#{appURL},#{createTime}) </insert> <delete id="delete" parameterType="String"> DELETE FROM applications WHERE appAccount = #{appAccount} </delete> <update id="update" parameterType="Application"> UPDATE applications <set> <if test=" appName != '' and appName != null "> appName = #{appName}, </if> <if test=" appICON != '' and appICON != null "> appICON = #{appICON}, </if> <if test=" appDesc != '' and appDesc != null "> appDesc = #{appDesc}, </if> <if test=" appURL != '' and appURL != null "> appURL = #{appURL}, </if> <if test=" isDisable != -1 "> isDisable = #{isDisable} </if> </set> WHERE appAccount = #{appAccount} </update> <select id="findByAppAccount" resultType="Application" parameterType="String"> select * from applications where appAccount = #{appAccount} </select> <select id="findAll" resultType="Application"> select * from applications </select> </mapper>
对ApplicationsMapper.xml文件的配置必须要注意的是它的命名空间是必须的,而且是对应接口文件的全名!并且每个sql语句的id属性和接口文件中的方法名一致!!
下面是ApplicationsMapper.java文件,也就是对应的接口文件:
package com.pinche.statistic.mapper; import java.util.List; import com.pinche.statistic.domain.Application; public interface ApplicationsMapper { void add(Application app); void delete(String appAccount); void update(Application app); Application findByAppAccount(String appAccount); List<Application> findAll(); }
通过以上的的配置,大家可以在test中测试一下自己的代码了
@Test public void testCreateTable() { ApplicationContext aContext = new FileSystemXmlApplicationContext("src/main/webapp/WEB-INF/applicationContext.xml"); ApplicationsMapper mapper = (ApplicationsMapper) aContext.getBean(ApplicationsMapper.class); Application app = new Application(); app.setAppAccount("androidApp"); mapper.add(app); }
以上测试了add方法,其他的测试方法大家可以照着写一写。如果插入成功恭喜,你的环境已经搭好了。
接下来是将继续这个样例系统的Dao层,service层和controller层。
这个dao层吧,项目中就是这么用的,不过现在通过大家的指正,mybatis提供了@param来解决多参数问题,ok,这么看来这个Dao层的确不需要了。
package com.pinche.statistic.dao; import java.util.List; import com.pinche.statistic.domain.Application; public interface AppDao { boolean add(Application app); boolean delete(String appAccount); boolean update(Application app); Application findByAppAccount(String appAccount); List<Application> findAll(); }
package com.pinche.statistic.dao.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Repository; import com.pinche.statistic.dao.AppDao; import com.pinche.statistic.domain.Application; import com.pinche.statistic.mapper.ApplicationsMapper; @Repository public class AppDaoImpl implements AppDao { @Autowired private ApplicationsMapper mapper; @Override public boolean add(Application app) { try { mapper.add(app); return true; } catch (DataAccessException e) { e.printStackTrace(); } return false; } @Override public boolean delete(String appAccount) { try { mapper.delete(appAccount); return true; } catch (DataAccessException e) { e.printStackTrace(); } return false; } @Override public boolean update(Application app) { try { mapper.update(app); return true; } catch (DataAccessException e) { e.printStackTrace(); } return false; } @Override public Application findByAppAccount(String appAccount) { try { Application findByAppAccount = mapper.findByAppAccount(appAccount); return findByAppAccount; } catch (DataAccessException e) { e.printStackTrace(); } return null; } @Override public List<Application> findAll() { try { return mapper.findAll(); } catch (DataAccessException e) { e.printStackTrace(); } return null; } }
自行设计的DAO层对象容器(在DAO对象很多时,如果在service层要调用对应的DAO还得手动注入,通过引用这个DAO层对象容器,可以实现在需要使用DAO时迅速找需要的DAO,省去了繁杂的手动注入,而且spring默认的bean都是单例的,无论在何处注入一个实体bean其实都是同一个。这样做更方便):
package com.pinche.statistic.dao; import java.lang.reflect.Field; import javax.annotation.PostConstruct; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; @Repository public class BaseDAL { private static final Logger logger = LoggerFactory.getLogger(BaseDAL.class); @Autowired private AppDao _appDao; public static AppDao appDao; @Autowired private MetaDataDao _metaDataDao; public static MetaDataDao metaDataDao; @Autowired private DDLManager _DDLManager; public static DDLManager DDLManager; @Autowired private AnalyzeDao _analyzeDao; public static AnalyzeDao analyzeDao; @Autowired private DialstatisticsDao _dialstatisticsDao; public static DialstatisticsDao dialstatisticsDao; @PostConstruct public void init() { long start = System.currentTimeMillis(); logger.debug("start init BaseDAL ..."); try { Field[] fields = this.getClass().getDeclaredFields(); for (int i = 0; i < fields.length; i++) { String fieldname = fields[i].getName(); if (fieldname.startsWith("_")) { String sfieldname = fieldname.substring(1); Field sfield = this.getClass().getDeclaredField(sfieldname); sfield.setAccessible(true); sfield.set(this, fields[i].get(this)); } } logger.debug("init BaseDAL OVER, consume = {}ms", System.currentTimeMillis() - start); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
如果使用了以上的层管理容器,如果要在容器中添加一个DAO(例如:DemoDao),只需在这个容器中添加一个这样的声明:
@Autowired private DemoDao _demoDao; public static DemoDao demoDao;
package com.pinche.statistic.service; import java.util.List; import com.pinche.statistic.domain.Application; /** * @author JACKWANG * @since Dec 23, 2013 */ public interface AppService { Application find(String appAccount); boolean update(Application app); boolean setDisable(String appAccount); boolean setEnable(String appAccount); List<Application> findAll(); }
package com.pinche.statistic.service.impl; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import com.pinche.statistic.dao.BaseDAL; import com.pinche.statistic.domain.Application; import com.pinche.statistic.service.AppService; import com.pinche.statistic.utils.SystemUtils; /** * @author JACKWANG * @since Dec 23, 2013 */ @Service public class AppServiceImpl implements AppService { private static final Logger logger = LoggerFactory .getLogger(AppServiceImpl.class); @Override public Application find(String appAccount) { return BaseDAL.appDao.findByAppAccount(appAccount); } @Override public boolean update(Application app) { String appAccount = app.getAppAccount(); if (appAccount == null && "".equals(appAccount)) { return true; } return BaseDAL.appDao.update(app); } @Override public boolean setDisable(String appAccount) { Application app = new Application(); app.setAppAccount(appAccount); app.setIsDisable(Application.APP_DISABLE); return BaseDAL.appDao.update(app); } @Override public boolean setEnable(String appAccount) { Application app = new Application(); app.setAppAccount(appAccount); app.setIsDisable(Application.APP_ENABLE); return BaseDAL.appDao.update(app); } @Override public List<Application> findAll() { return BaseDAL.appDao.findAll(); } }
哈哈,使用层对象管理容器是不是很方便。通过一个引用就能获得所有的DAO支持。所以我在service层也构建了一个service层对象管理容器BaseBLL:
package com.pinche.statistic.service; import java.lang.reflect.Field; import javax.annotation.PostConstruct; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @author JACKWANG * @since Dec 23, 2013 */ @Service public class BaseBLL { private static final Logger logger = LoggerFactory.getLogger(BaseBLL.class); @Autowired private AnalyzeService _analyzeService; public static AnalyzeService analyzeService; @Autowired private AppService _appService; public static AppService appService; @Autowired private MetaDataService _metaDataService; public static MetaDataService metaDataService; @PostConstruct public void init() { long start = System.currentTimeMillis(); logger.debug("start init BaseBLL ..."); try { Field[] fields = this.getClass().getDeclaredFields(); for (int i = 0; i < fields.length; i++) { String fieldname = fields[i].getName(); if (fieldname.startsWith("_")) { String sfieldname = fieldname.substring(1); Field sfield = this.getClass().getDeclaredField(sfieldname); sfield.setAccessible(true); sfield.set(this, fields[i].get(this)); } } logger.debug("init BaseBLL OVER, consume = {}ms", System.currentTimeMillis() - start); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
好了下面应该是controller层的编写了,但是由于笔者以上的代码只是摘录了系统中的部分,而在controller中涉及到其他的内容,如果直接摘录可能和以上的代码衔接不上。所以这里就不进行了controller层的具体介绍了。本系统controller层使用的是SpringMVC,开发效率一级赞。
package com.pinche.statistic.dao; import java.util.List; import com.pinche.statistic.domain.Application; public interface AppDao { boolean add(Application app); boolean delete(String appAccount); boolean update(Application app); Application findByAppAccount(String appAccount); List<Application> findAll(); }
package com.pinche.statistic.dao.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Repository; import com.pinche.statistic.dao.AppDao; import com.pinche.statistic.domain.Application; import com.pinche.statistic.mapper.ApplicationsMapper; @Repository public class AppDaoImpl implements AppDao { @Autowired private ApplicationsMapper mapper; @Override public boolean add(Application app) { try { mapper.add(app); return true; } catch (DataAccessException e) { e.printStackTrace(); } return false; } @Override public boolean delete(String appAccount) { try { mapper.delete(appAccount); return true; } catch (DataAccessException e) { e.printStackTrace(); } return false; } @Override public boolean update(Application app) { try { mapper.update(app); return true; } catch (DataAccessException e) { e.printStackTrace(); } return false; } @Override public Application findByAppAccount(String appAccount) { try { Application findByAppAccount = mapper.findByAppAccount(appAccount); return findByAppAccount; } catch (DataAccessException e) { e.printStackTrace(); } return null; } @Override public List<Application> findAll() { try { return mapper.findAll(); } catch (DataAccessException e) { e.printStackTrace(); } return null; } }
自行设计的DAO层对象容器(在DAO对象很多时,如果在service层要调用对应的DAO还得手动注入,通过引用这个DAO层对象容器,可以实现在需要使用DAO时迅速找需要的DAO,省去了繁杂的手动注入,而且spring默认的bean都是单例的,无论在何处注入一个实体bean其实都是同一个。这样做更方便):
package com.pinche.statistic.dao; import java.lang.reflect.Field; import javax.annotation.PostConstruct; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; @Repository public class BaseDAL { private static final Logger logger = LoggerFactory.getLogger(BaseDAL.class); @Autowired private AppDao _appDao; public static AppDao appDao; @Autowired private MetaDataDao _metaDataDao; public static MetaDataDao metaDataDao; @Autowired private DDLManager _DDLManager; public static DDLManager DDLManager; @Autowired private AnalyzeDao _analyzeDao; public static AnalyzeDao analyzeDao; @Autowired private DialstatisticsDao _dialstatisticsDao; public static DialstatisticsDao dialstatisticsDao; @PostConstruct public void init() { long start = System.currentTimeMillis(); logger.debug("start init BaseDAL ..."); try { Field[] fields = this.getClass().getDeclaredFields(); for (int i = 0; i < fields.length; i++) { String fieldname = fields[i].getName(); if (fieldname.startsWith("_")) { String sfieldname = fieldname.substring(1); Field sfield = this.getClass().getDeclaredField(sfieldname); sfield.setAccessible(true); sfield.set(this, fields[i].get(this)); } } logger.debug("init BaseDAL OVER, consume = {}ms", System.currentTimeMillis() - start); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
如果使用了以上的层管理容器,如果要在容器中添加一个DAO(例如:DemoDao),只需在这个容器中添加一个这样的声明:
@Autowired private DemoDao _demoDao; public static DemoDao demoDao;
package com.pinche.statistic.service; import java.util.List; import com.pinche.statistic.domain.Application; /** * @author JACKWANG * @since Dec 23, 2013 */ public interface AppService { Application find(String appAccount); boolean update(Application app); boolean setDisable(String appAccount); boolean setEnable(String appAccount); List<Application> findAll(); }
package com.pinche.statistic.service.impl; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import com.pinche.statistic.dao.BaseDAL; import com.pinche.statistic.domain.Application; import com.pinche.statistic.service.AppService; import com.pinche.statistic.utils.SystemUtils; /** * @author JACKWANG * @since Dec 23, 2013 */ @Service public class AppServiceImpl implements AppService { private static final Logger logger = LoggerFactory .getLogger(AppServiceImpl.class); @Override public Application find(String appAccount) { return BaseDAL.appDao.findByAppAccount(appAccount); } @Override public boolean update(Application app) { String appAccount = app.getAppAccount(); if (appAccount == null && "".equals(appAccount)) { return true; } return BaseDAL.appDao.update(app); } @Override public boolean setDisable(String appAccount) { Application app = new Application(); app.setAppAccount(appAccount); app.setIsDisable(Application.APP_DISABLE); return BaseDAL.appDao.update(app); } @Override public boolean setEnable(String appAccount) { Application app = new Application(); app.setAppAccount(appAccount); app.setIsDisable(Application.APP_ENABLE); return BaseDAL.appDao.update(app); } @Override public List<Application> findAll() { return BaseDAL.appDao.findAll(); } }
哈哈,使用层对象管理容器是不是很方便。通过一个引用就能获得所有的DAO支持。所以我在service层也构建了一个service层对象管理容器BaseBLL:
package com.pinche.statistic.service; import java.lang.reflect.Field; import javax.annotation.PostConstruct; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @author JACKWANG * @since Dec 23, 2013 */ @Service public class BaseBLL { private static final Logger logger = LoggerFactory.getLogger(BaseBLL.class); @Autowired private AnalyzeService _analyzeService; public static AnalyzeService analyzeService; @Autowired private AppService _appService; public static AppService appService; @Autowired private MetaDataService _metaDataService; public static MetaDataService metaDataService; @PostConstruct public void init() { long start = System.currentTimeMillis(); logger.debug("start init BaseBLL ..."); try { Field[] fields = this.getClass().getDeclaredFields(); for (int i = 0; i < fields.length; i++) { String fieldname = fields[i].getName(); if (fieldname.startsWith("_")) { String sfieldname = fieldname.substring(1); Field sfield = this.getClass().getDeclaredField(sfieldname); sfield.setAccessible(true); sfield.set(this, fields[i].get(this)); } } logger.debug("init BaseBLL OVER, consume = {}ms", System.currentTimeMillis() - start); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
好了下面应该是controller层的编写了,但是由于笔者以上的代码只是摘录了系统中的部分,而在controller中涉及到其他的内容,如果直接摘录可能和以上的代码衔接不上。所以这里就不进行了controller层的具体介绍了。本系统controller层使用的是SpringMVC,开发效率一级赞。