Springユーティリティ--Profile、WebService、キャッシュ、メッセージ、ORM


この記事では、Apache CXF WebServiceフレームワーク、Redisキャッシュ、RabbitMQメッセージ、MyBatisフレームワークなど、Springと他のフレームワークを組み合わせた実用的な機能について説明します.
またProfileについてもSpring 3.0新しく追加した機能を開始することは、開発テスト環境と生産環境にそれぞれ異なる配置を採用することに対して、一定の用途がある.
Profile
Spring3.1新しい属性管理API:PropertySource、Environment、Profile.
Environment:環境自体はPropertyResolverですが、環境に応じて対応するデータを得ることができるProfileプロパティが提供されています(つまり、異なるProfileをアクティブにすることで、マルチ環境シーン用の構成(本番機、テスト機、開発機Data Source構成)など、異なるプロパティデータを得ることができます).
Profile:断面、アクティブな断面のコンポーネント/構成のみがSpringコンテナに登録されます.mavenのprofileと同様に、Spring 3.1は異なる環境間で簡単に切り替えるprofile概念を追加し、ファイルを変更せずにdev/test/productionなどの環境でプロジェクトを実行できます.
配置メンテナンスを低減するために、プロジェクトはdevモードでデフォルトで実行され、テスト環境と生産環境はjvmパラメータを増やしてproductionのprofileをアクティブにすることができる.
たとえば、次の例では、テスト環境と本番環境でデータベースを接続する方法が異なるため、次のような解決策があります.
1、まずApplicationContext.xmlでは、xsi:schemaLocationは3.2のxsdを参照する必要があります.
2、ApplicationContext.xmlの構成は次のとおりです.
<beans profile="production">
	<bean id="dataSourcejdbc" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiName" value="java:/MySqlDS_JDBC" />
	</bean>
</beans>
<beans profile="dev">
	<bean id="dataSourcejdbc" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://IP:3306/db?characterEncoding=utf-8"/>
		<property name="username" value="root"/>
		<property name="password" value="root"/>
	</bean>
</beans>

3、開発環境の配置、web.xmlでは、次のように構成されています.
<context-param>  
	<param-name>spring.profiles.default</param-name>  
	<param-value>dev</param-value>  
</context-param>

4、生産環境の配置
例えば、Jbossの場合bin/run.confでは、起動パラメータ:-DPスプリングを追加します.profiles.active=production
JAVA_OPTS="-Xms2048m -Xmx2048m -XX:MaxPermSize=1024m -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Dsun.lang.ClassLoader.allowArraySyntax=true -Dorg.terracotta.quartz.skipUpdateCheck=true -Dspring.profiles.active=production"
以上、Webプロジェクトでprofileをどのように利用するかについてのプレゼンテーションですが、mavenプロジェクトであれば、mavenパッケージ時に異なるprofileを採用することもできます.コマンドは以下の通りです.
mvn clean package -Dmaven.test.skip=true -Ponline
Pパラメータによって異なるprofileを採用することで,開発,テスト,生産のために異なるパッケージを打ち出すことができる.
しかし、このパッケージ方式は推奨されず、開発、テスト、生産に対して同じパッケージを打ち出し、機械自体の環境に応じてプログラムをその環境で実行することを決定するべきである.
このprofileは、dev/test/stage/onlineなどの環境変数に基づいた自動化された導入方法がある場合に便利です.
WebService
Java生態下のWebServiceフレームワークは非常に多く、apache cxfはspringと結合するのに最も良いものです.構成手順は次のとおりです.
1、pom.xml、依存度を増加:
<dependency>
	<groupId>org.apache.cxf</groupId>
	<artifactId>cxf-rt-frontend-jaxws</artifactId>
	<version>2.7.5</version>
</dependency>
<dependency>
	<groupId>org.apache.cxf</groupId>
	<artifactId>cxf-rt-transports-http</artifactId>
	<version>2.7.5</version>
</dependency>

2、web.xml、servletを追加:
<!-- Web Service     -->
<servlet>
    <servlet-name>cxf</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>cxf</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>
<!-- Web Service     -->

3.resourcesディレクトリの下にアプリケーションContext-cxfを追加する.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:jaxws="http://cxf.apache.org/jaxws"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

 <!-- <import resource="classpath:META-INF/cxf/cxf.xml" />
 <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> -->

 <jaxws:endpoint implementor="#basicWebService" address="/BasicWebService" />
</beans>

4、BasicWebServiceからの内容は大体以下の通りです.
@WebService(name = "BasicWebService", serviceName = "BasicWebService", portName = "BasicWebServicePort", targetNamespace = "http://api.domain.com/ws")
@Service
public class BasicWebService {
 @WebMethod
 public void sendHtmlMail(@WebParam(name = "headName") String headName,
   @WebParam(name = "sendHtml") String sendHtml) {
  sendMail.doSendHtmlEmail(headName, sendHtml);
 }
}

Apache CXFフレームワークを使用すると、Springコンテナによって管理されます.つまり、BasicWebService自体で@Serviceタグを設定したり、BasicWebServiceで@Autowiredを使用して注入したりすることができます.
他のフレームワークのWebService、例えばJbossが直接サーブレットで露出しているWebServiceは、SpringContextHolderがSpringコンテナから手動で取り出すことはできません.大体次のようになります.
1、まずweb.xmlにWebServiceクラスのservletを追加します.次のようにします.
<!-- Web Service     -->
<servlet>
	<servlet-name>BasicWebService</servlet-name>
	<servlet-class>com.xx.BasisWebService</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>BasicWebService</servlet-name>
	<url-pattern>/BasicWebService</url-pattern>
</servlet-mapping>
<!-- Web Service     -->  

2、BasicWebServiceの内容は大体以下の通りです.
@WebService(name = "BasicWebService", serviceName = "BasicWebService", portName = "BasicWebServicePort", targetNamespace = "http://api.sina.com/ws")
public class BasicWebService {

	//   Spring      ,SpringContextHolder      org.springframework.context.ApplicationContextAware  
	private ISystemConfigService systemConfigService = SpringContextHolder.getBean(ISystemConfigService.class);

	@WebMethod
	public String test(@WebParam(name = "inputpara") String inputpara) {
		return inputpara + "_100";
	}
}

Redis
SpringはRedisを呼び出す操作を簡略化することができ、構成は大体以下の通りである.
1、pom.xml依存度の増加:
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-redis</artifactId>
	<version>1.0.6.RELEASE</version>
</dependency>

2.resourcesディレクトリの下に、アプリケーションContext-redisを追加する.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:cache="http://www.springframework.org/schema/cache"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
 http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">    
    <description>Spring-cache</description>
    <cache:annotation-driven/>
    <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
        <constructor-arg name="template" index="0" ref="redisTemplate"/>
    </bean>
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxActive" value="${redis.pool.maxActive}"/>
        <property name="maxIdle" value="${redis.pool.maxIdle}"/>
        <property name="maxWait" value="${redis.pool.maxWait}"/>
        <property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>
    </bean>
    <!--     : -->
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.ip}"/>
        <property name="port" value="${redis.port}"/>
        <property name="poolConfig" ref="jedisPoolConfig"/>
    </bean>
    <!--   : -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="jedisConnectionFactory">
        <property name="keySerializer" ref="stringRedisSerializer"/>
    </bean>
    <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</beans>

3、キャッシュライトリファレンス実装:
@Service
public class BrandBaseServiceImpl implements IBrandBaseService {
    @Override
    @Cacheable(value = CacheClientConstant.COMMODITY_BRAND_REDIS_CACHE, key = "'commodity:webservice:all:brand:list'")
    public List<Brand> getAllBrands() {
     try
     {
      List<Brand> brands = brandMapper.getAllBrands();
      return brands;
     } catch (Exception ex)
     {
      logger.error(ex.toString());
      return null;     
     }
    }
    @Override
    @Cacheable(value = CacheClientConstant.COMMODITY_BRAND_REDIS_CACHE, key = "'commodity:webservice:brand:no:'+#brandNo")
    public Brand getBrandByNo(String brandNo) {
        if (StringUtils.isBlank(brandNo))
            return null;
        return brandMapper.getBrandByNo(brandNo);
    }
}

4、キャッシュクリアリファレンス実装:
@Service
public class RedisCacheUtil {
 
 private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private JedisConnectionFactory jedisConnectionFactory;    
    @CacheEvict(value = CacheClientConstant.COMMODITY_CATEGORY_REDIS_CACHE, key = "'commodity:webservice:category:no:'+#categoryNo")
    public void cleanCatCacheByNo(String categoryNo)
    {
     List<String> keys = new ArrayList<String>();
        logger.info("[     ]    categoryNo:{}  ,REDIS SERVER  :{}", categoryNo, jedisConnectionFactory.getHostName() + ":" + jedisConnectionFactory.getPort());
        if (StringUtils.hasText(categoryNo)) {
         keys.add("commodity:webservice:category:no:" + categoryNo);
            cleanAgain(keys);
        }
    }    
    @CacheEvict(value = CacheClientConstant.COMMODITY_SYSTEMCONFIG_REDIS_CACHE, allEntries = true)
    public void cleanSystemConfigAll()
    {
     logger.info("[     ]  SystemConfig  ");
    }    
    /**
     *                   ,         
     * @param keys        KEY
     */
    private void cleanAgain(List<String> keys) {
        if (CollectionUtils.isEmpty(keys)) {
            return;
        }
        for (String key : keys) {
            logger.info("    ,KEY:{}", key);
            redisTemplate.delete(key);
        }
    }
}  

RabbitMQ
SpringはRabbitMQの操作を簡略化することもでき、構成は大体以下の通りである.
1、pom.xml依存度の増加:
<dependency>
	<groupId>org.springframework.amqp</groupId>
	<artifactId>spring-amqp</artifactId>
	<version>${spring.amqp.version}</version>
</dependency>
<dependency>
	<groupId>org.springframework.amqp</groupId>
	<artifactId>spring-rabbit</artifactId>
	<version>${spring.amqp.version}</version>
</dependency>

2、メッセージコードの送信例:
@Service
public class MessageSendServiceImpl implements IMessageSendService { 
 private static final String EXCHANGE = "amq.topic"; 
 @Autowired
 private volatile RabbitTemplate rabbitTemplate; 
 private final Logger logger = LoggerFactory.getLogger(this.getClass());
 @Override
 public Boolean sendMessage(String commodityNo) {
  Commodity c = getCommodity(commodityNo);
  //   rabbitMQ  (topic)
  rabbitTemplate.convertAndSend(EXCHANGE, "commodity.update.topic", c);
  logger.info("      (topic):    :" + commodityNo);
  return true;
 } 
}

3.resourcesディレクトリの下に、アプリケーションContext-rabbitmqを追加する.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:rabbit="http://www.springframework.org/schema/rabbit" xmlns:task="http://www.springframework.org/schema/task"
 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/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.1.xsd
 http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 <!--   rabbitmq    ,          ,  failover,rabbitmq.host=192.168.211.230:5672 -->
 <rabbit:connection-factory id="connectionFactory" addresses="${rabbitmq.host}" />
 <rabbit:admin connection-factory="connectionFactory" />
 <rabbit:template id="amqpTemplate" connection-factory="connectionFactory" channel-transacted="true"
  message-converter="jsonMessageConverter" />
 <bean id="jsonMessageConverter" class="org.springframework.amqp.support.converter.JsonMessageConverter">
  <property name="classMapper">
   <bean class="org.springframework.amqp.support.converter.DefaultClassMapper">
   </bean>
  </property>
 </bean>
 <!--
          :
    1.               ,            ,    name,<rabbit:listener   queues=   name
    2.               ,             ,     name, rabbitmq       name,        name  ,   <rabbit:listener  queues=   id
        ,           
 -->    
    <rabbit:queue id="queue id,   name  " name="queue   , rabbitmq       ,  commodity.update.topic.queue">
        <rabbit:queue-arguments>
            <entry key="x-ha-policy" value="all" />
        </rabbit:queue-arguments>
    </rabbit:queue> 
 <!-- CONSUMER -->
    <!--    error-handler     ,  rabbitmq            ,      error-handler,log       amqp  ,              -->
 <rabbit:listener-container connection-factory="connectionFactory" message-converter="jsonMessageConverter" 
            channel-transacted="true" error-handler="rabbitMqErrorHandler" concurrency="10"
               auto-startup="true">
        <rabbit:listener queues="rabbit:queue    name  id" ref="commodityUpdateListener" method="handleMessage" />
    </rabbit:listener-container>
    <rabbit:topic-exchange name="amq.topic" >
        <rabbit:bindings>
            <!--    queue <rabbit:queue   ID -->            
            <rabbit:binding pattern="    routingKey,         commodity.update.topic" queue="queue   , rabbitmq       ,  commodity.update.topic.queue"/>
        </rabbit:bindings>
    </rabbit:topic-exchange>
</beans>
4、受信メッセージコード例:
@Component
public class CommodityUpdateListener {
 public void handleMessage(Commodity commodity) {
  if(commodity==null)
  {
   logger.info("XXX");
   return;
  }
  //    
 }
}

5、処理メッセージエラーコード例:
@Component
public class RabbitMqErrorHandler implements ErrorHandler {
 
 private static Logger logger = LoggerFactory.getLogger(RabbitMqErrorHandler.class);
 
 @Override
 public void handleError(Throwable t) {
  logger.error("Receive rabbitmq message error:{}", t); 
 }
}

MyBatis
SpringはMyBatisというORMフレームワークを大幅に簡略化し、インタフェースとMapperファイルを定義した後、Springは自動的に実装クラスを生成することができます.DotNetフレームワークでMyBatisを使ったことがあります.Net、すべてのMapperの実装クラスは手動でコードを書く必要がありますが、Springは多くの符号化作業量を節約してくれました.
大まかな構成手順は次のとおりです.
1、pom.xml依存度の増加:
<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis-spring</artifactId>
	<version>1.1.1</version>
</dependency>
<dependency>
	<groupId>org.mybatis.caches</groupId>
	<artifactId>mybatis-ehcache</artifactId>
	<version>1.0.1</version>
</dependency>

2.resourcesディレクトリの下、アプリケーションContext.xmlでは、mybatisの構成について一般的に配置されます.内容は次のとおりです.
<?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:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
 http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
 http://www.springframework.org/schema/jee  http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
 http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.2.xsd
 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
 <description>Spring    </description>
 <!--     -->
 <context:annotation-config />
 <!--          -->
 <aop:aspectj-autoproxy /> 
 <context:component-scan base-package="com.xx">
  <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
 </context:component-scan>
 <!--              -->
 <bean 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*:/application.properties</value>
    <value>classpath*:/config.properties</value>
    <!--          -->
    <value>file:/d:/conf/pcconf/*.properties</value>
    <!--           -->
    <value>file:/etc/conf/pcconf/*.properties</value>
   </list>
  </property>
  <!--property name="ignoreUnresolvablePlaceholders" value="true" / -->
 </bean>
 <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     <property name="dataSource" ref="dataSourcejdbc"/>    
    </bean>
 <!--      JdbcTemplate  JdbcUtils -->
 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  <property name="dataSource" ref="dataSourcejdbc" />
 </bean>
 <bean id="sqlSessionFactoryWrite" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSourcejdbc" />
 </bean>
 <!--     basePackage             @Mapper   Dao        ,       Dao  。 -->
 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="sqlSessionFactory" ref="sqlSessionFactoryWrite" />
  <property name="basePackage" value="com/xx/pc/template" />
 </bean> 
 <beans profile="production">
  <bean id="dataSourcejdbc" class="org.springframework.jndi.JndiObjectFactoryBean">
   <property name="jndiName" value="java:/MySqlDS_JDBC" />
  </bean>
 </beans>
    <beans profile="dev">
     <bean id="dataSourcejdbc" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
         <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
      <property name="url" value="jdbc:mysql://ip:3306/dbname?characterEncoding=utf-8"/>
      <property name="username" value="root"/>
      <property name="password" value="root"/>
     </bean>
    </beans> 
</beans>
3、インタフェースの定義、およびsrc/main/resource対応インタフェースのパケットパスの下で同名のxmlプロファイルを定義すればよい.
Spring初期化が完了すると、自動的にMapperの実装クラスを生成してくれます.