Spring整合框架配置總結

 

1. Spring Data JPA 配置:

0.框架知識概述:

Spring Data JPA  是一個持久層的框架,而一個持久層框架所做的事情不過兩件:

  1. 連接數據庫(比如 JDBD連接數據庫) 2.操作數據庫(比如 sql 操作數據庫);
  1. 連接數據庫:
  1. 配置參數抽取:  config.properties 配置:

# oracle jdbc properties

jdbc.url = jdbc:oracle:thin:@localhost:1521:XE

jdbc.driver= oracle.jdbc.driver.OracleDriver

jdbc.user = bos

jdbc.password = bos

  1. applicationContext-dataSource.xml 配置:
  1. 數據庫連接池配置: config.properties

在主配置文件 applicationContext.xml 中通過配置加載屬性文件:

<!-- 加載properties文件 -->

<context:property-placeholder location="classpath:config.properties" />

( ${jdbc.url} 這種類似EL表達式的是SpringEL 表達式  )

<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.user}" />

<property name="password" value="${jdbc.password}" />

</bean>

  1. Spring整合JPA配置:

(在 entityManagerFactory中配置了連接池 和 domain中的bean ,這就相當於是用連接把實體類與數據庫表建立了聯繫,這種聯繫是非常緊密的,實體對象屬性的變化直接會反映到數據庫表中, 而JPA作爲接口規範,這裏選擇 hibernate作爲持久化提供者; 然後就是一些數據庫的基本配置了;)

<!-- 整合JPA配置 -->

<bean id="entityManagerFactory"

class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<property name="dataSource" ref="dataSource" />

<property name="packagesToScan" value="cn.itcast.bos.domain" />

<property name="persistenceProvider">

<bean class="org.hibernate.jpa.HibernatePersistenceProvider" />

</property>

<property name="jpaVendorAdapter">

<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

<property name="generateDdl" value="true" />

<property name="database" value="ORACLE" />

<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />

<property name="showSql" value="true" />

</bean>

</property>

<property name="jpaDialect">

<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />

</property>

<!-- <property name="jpaPropertyMap"> -->

<!-- <map> -->

<!-- <entry key="hibernate.query.substitutions" value="true 1, false 0" /> -->

<!-- <entry key="hibernate.default_batch_fetch_size" value="16" /> -->

<!-- <entry key="hibernate.max_fetch_depth" value="2" /> -->

<!-- <entry key="hibernate.generate_statistics" value="true" /> -->

<!-- <entry key="hibernate.bytecode.use_reflection_optimizer" -->

<!-- value="true" /> -->

<!-- <entry key="hibernate.cache.use_second_level_cache" value="false" /> -->

<!-- <entry key="hibernate.cache.use_query_cache" value="false" /> -->

<!-- </map> -->

<!-- </property> -->

</bean>

2.操作數據庫:

  1. 整合Spring Data JPA  (相當於掃描了Dao, 這樣dao的操作才能別識別;)

<!-- 整合spring data jpa -->

<jpa:repositories base-package="cn.itcast.bos.dao" />

3.聲明式事務管理配置:

1. 配置事務管理器:

(JDBC事務管理的本質,是對Session的管理, 那麼這裏配置了事務管理器, 就相當於指明瞭由誰來管理事務, 而同時屬性注入了 entityManagerFactory 實體管理者工廠,這就相當於將數據庫操作中的session交給了事務管理器,也就容易實現事務的管理了)

<!-- JPA事務管理器  -->

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" >

<property name="entityManagerFactory" ref="entityManagerFactory" />

</bean>

  1. 配置事務註解驅動 

(這樣就可以識別 Service 中的 @Transactional了)

<!-- 註解管理事務 -->

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

4.Spring Data JPA 配置小結:

1. SpringDataJPA 的配置就是通過將基本數據庫連接參數:比如driven , url ,  username, password通過屬性注入到連接池DataSource, 這個時候連接池其實已經拿到了數據庫的連接connection, 理論上已經可以通過sql操作數據庫了,但是此時我們又將: dataSource, , domain , persistenceProvider 通過屬性注入到 entityManagerFactory ,其實這個時候 ”實體管理者工廠” 已經利用 DataSource中的 connection 將 domain 下的實體類 entity 與數據庫中的表 table 建立了緊密聯繫, 此時已經完成了類與表的強相關; 至此,我們對數據庫的操作對象不再是真真正正的表了,而是與之強相關的類了,操作的實現不再是sql語句,而是使用方法來實現了; 至於哪個類對應哪個表,這就是 映射文件 hbm.xml 或者是類中的映射註解配置來細化了;

2. 在第1步獲得類與數據庫的連接以後,我們就要操作數據庫了,我們是通過:

<jpa:repositories base-package="cn.itcast.bos.dao" />

這個相當於是掃描指定包下的 repository 接口, (當然這些repository 繼承了jpaRepository,或者JpaSpecificationExecutor接口), 這樣其實底層也是利用了AOP 當我們在Service中 @autowired 這些接口實現時, AOP 會給我們注入 SpringDataJPA 默認實現類,這些實現了本身已經封裝了一些常見的CRUD操作,所以我們可以省去常見CRUD操作的sql的編寫,但是對於一些複雜的CRUD操作, SpringDataJPA 也給我們留了一個口子:

  1. 比如一些標準的操作:
    1. findById()  ,  findByProvinceAndCityAndDistrict 等
    2. 更復雜的操作:

@Query(value="update Courier set deltag='1' where id=?")

@Modifying

public void updateDeltag(int id);

或者是這個:

@Query(value="update Courier set deltag='' where id=?")

@Modifying

public void doRestore(int id);

3 . 至於事務管理: 原理是Spring 有IOC ,那麼類的創建,準確來說是Service類的創建,也是由Spring來創建, 根據Spring創建bean的生命週期方法的執行流程,我們知道,後處理bean中的方法執行在我們獲得bean對象之前,那麼,在後處理bean彙總利用AOP思想,在我們獲得的Service的方法前都加上session的事務開啓,在方法執行後加上session的事務提交,和事務回滾,那麼在我們拿到IOC 容器給我們創建的bean時,這個bean就是在事務管理之中的bean了; 這就完成了事務管理;

===============以上SpringDataJPA== 以下 WebService====================

  1. WebService的配置:

0.框架知識概述:

(WebService 按目前使用來看就是提供了跨服務器遠程數據獲取的一種方式, 那我們只會關心兩個問題: 1. 遠程服務的創建與發佈, 2,本地對遠程服務的訪問與數據接收; 其實遠程服務的創建,就是一個service接口 中方法訪問路徑,訪問方式,接收數據格式,返回數據格式的聲明, 至於服務的發佈其實是交給了配置文件; 至於本地客戶端可能只需要WebClient 加上一個正確格式的url就可以了)我們這裏說一下 JAX-RS 的配置:

1.首先說以下服務端配置:

  1. 作爲一個服務提供端,它需要識別到對 它的所有WebService請求, 那麼它就是通過在 web.xml中配置一個 CXFServlet 用來專門接收並處理WebService請求:

比如下面配置會攔截所有端口號後以 /services 開頭的url請求:

<servlet>

<servlet-name>CXFService</servlet-name>

<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>CXFService</servlet-name>

<url-pattern>/services/*</url-pattern>

</servlet-mapping>

  1. 在第1步攔截到所有WebService請求的基礎上,它會根據請求的url 去尋找對應的Service , 那麼到哪裏去尋找呢? 當然是到已經發布到服務器中的Service中去找, 那麼怎麼纔算是發佈到服務器中了呢? 這裏我們是通過在 .xml配置文件來實現發佈的:

比如下面配置 是將 PromotionServiceImpl  發佈到服務器中

<jaxrs:server id="promotionService" address="/promotionService">

<jaxrs:serviceBeans>

<bean class="cn.itcast.bos.service.take_delivery.impl.PromotionServiceImpl" />

</jaxrs:serviceBeans>

<jaxrs:inInterceptors>

<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>

</jaxrs:inInterceptors>

<jaxrs:outInterceptors>

<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>

</jaxrs:outInterceptors>

</jaxrs:server>

--------------------------------下面附上 Service接口中方法聲明---------------------------------------

// 根據page和rows 返回分頁數據

@Path("/pageQuery")

@GET

@Produces({ "application/xml", "application/json" })

PageBean<Promotion> findPageData(@QueryParam("page") int page,

@QueryParam("rows") int rows);

--------------------------------下面附上 Service實現編寫示例---------------------------------------

@Override

public PageBean<Promotion> findPageData(int page, int rows) {

Pageable pageable = new PageRequest(page - 1, rows);

Page<Promotion> pageData = promotionRepository.findAll(pageable);

// 封裝到Page對象

PageBean<Promotion> pageBean = new PageBean<Promotion>();

pageBean.setTotalCount(pageData.getTotalElements());

pageBean.setPageData(pageData.getContent());

return pageBean;

}

2.服務端配置小結:

其實以上已經說明了Service 接口編寫, Service接口實現編寫, Service服務在服務器端發佈, 已經服務器端對 WebService 請求的攔截;

3.客戶端請求操作:

客戶端作爲服務的調用者,相對來說不需要特別的配置,只需要使用一個客戶端請求對象WebClient 加上正確的url 就可以發送請求了:其中 WebClient.create 創建了請求; .accept 指明瞭是接收數據(接收用accept, 發送用 type) ; .get 指明瞭請求方式是get請求(get請求是查詢操作, post請求是添加操作, put請求是更新操作, delete 請求是刪除操作)

@Action(value = "promotion_pageQuery", results = { @Result(name = "success", type = "json") })

public String pageQuery() {

// 基於WebService 獲取 bos_management的 活動列表 數據信息

PageBean<Promotion> pageBean = WebClient

.create(Constants.BOS_MANAGEMENT_URL

+ "/bos_management/services/promotionService/pageQuery?page="

+ page + "&rows=" + rows)

.accept(MediaType.APPLICATION_JSON).get(PageBean.class);

ActionContext.getContext().getValueStack().push(pageBean);

return SUCCESS;

}

4.WebService配置小結:

其實我們來理順整個過程: 客戶端 使用WebClient.create();發起請求-------->服務端 web.xml配置 CXFServlet 攔截所有 /services 開頭請求--------> applicationContext-webService.xml 發佈服務-------> Service接口中的具體方法, 聲明服務訪問方式,-------> Service實現類中 提供了服務真正的操作內容;

=================以上WebService  == 以下 ActiveMQ ======================

3.ActiveMQ 的配置:

0.框架知識概述:

ActiveMQ 是JMS java消息服務的規範的實現: 個人感覺它是一個服務器,有着自己的訪問端口,但是它的工作卻是存儲消息, 又很像一個存放消息的數據庫,所有在和 Spring整合時特像一個數據庫: 其實:ActiveMQ 的事情也是兩件:1.給生產者提供存放消息的入口, 2.給消費者提供消費消息的入口:

  1. 基礎連接配置:

無論是 “生產消息” 還是 “消費消息” :我們都要有基礎的連接配置:

  1. ActiveMQ 本身給我們提供了一個連接工廠: ActiveMQConnectionFactory

<!-- ActiveMQ 連接工廠 -->

<!-- 真正可以產生Connection的ConnectionFactory,由對應的 JMS服務廠商提供-->

<!-- 如果連接網絡:tcp://ip:61616;未連接網絡:tcp://localhost:61616 以及用戶名,密碼-->

下面這種連接方式需要是爲了簡化<bean>配置,但需要下載第三方的支持,開始運行時較慢:

<!--  <amq:connectionFactory id="amqConnectionFactory" -->

<!--  brokerURL="tcp://localhost:61616" userName="admin" password="admin" />  -->

<bean id="amqConnectionFactory"

class="org.apache.activemq.ActiveMQConnectionFactory">

<property name="brokerURL" value="tcp://localhost:61616"></property>

<property name="userName" value="admin"></property>

<property name="password" value="admin"></property>

</bean>

  1. Spring 對  ActiveMQ 連接工廠的封裝 CachingConnectionFactory

Spring在 JMS服務供應商提供連接工廠的基礎上,給我們進行了一次封裝,這個封裝可以理解成 Spring 提供的API 與 ActiveMQ 之間的適配器 ; 達到了解耦的作用, 這樣Spring就可以整合各個JMS供應商提供的連接工廠了;

<!-- Spring Caching連接工廠 -->

<!-- Spring用於管理真正的ConnectionFactory的ConnectionFactory -->  

<bean id="mqConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">

<!-- 目標ConnectionFactory對應真實的可以產生JMS Connection的ConnectionFactory -->  

<property name="targetConnectionFactory" ref="amqConnectionFactory"></property>

<!-- 同上,同理 -->

<!-- <constructor-arg ref="amqConnectionFactory" /> -->

<!-- Session緩存數量 -->

<property name="sessionCacheSize" value="1" />

</bean>

  1. 基礎配置小結

不管我們用那種JMS產品,它都會提供一個連接工廠,而與Spring整合時,我們用 CachingConnectionFactory  將JMS服務廠商提供的連接工廠進行封裝, 那麼我們就可以不需要針對不同的 連接工廠操作了,只需要對同一個 CachingConnectionFactory  盡心操作,達到了解耦的目的; 流程如下:

JMS廠商提供ActiveMQ 提供 ActiveMQConnectionFactory 連接工廠------>Spring 提供 CachingConnectionFactory 緩存連接工廠 封裝廠商提供的連接工廠

  1. 生產者配置:
  1. 這個消息生產者配置,Spring使用了它慣用的模板思想,給你提供了一個模板對象,沒有什麼特別之處,這個模板對象封裝了連接工廠,就相當於持有了對ActiveMQ的連接, 那麼這個時候向ActiveMQ中添加消息應該是可以的;  下邊配置了兩種類型的jmsTemplate: 1. 點對點模式: 隊列Queue,  2. 發佈訂閱模式的: 話題Topic ; 他們的配置大同小異,唯一不同之處在於 :

<property name="pubSubDomain" value="false" />

的配置的value 值是false 還是 true;  (true:發佈訂閱模式 false:點對點模式;)

<!-- 定義JmsTemplate的Queue類型 -->

<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">

<!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory對象 -->  

<constructor-arg ref="mqConnectionFactory" />

<!-- 非pub/sub模型(發佈/訂閱),即隊列模式 -->

<property name="pubSubDomain" value="false" />

</bean>

<!-- 定義JmsTemplate的Topic類型 -->

<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">

<!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory對象 -->  

<constructor-arg ref="mqConnectionFactory" />

<!-- pub/sub模型(發佈/訂閱) -->

<property name="pubSubDomain" value="true" />

</bean>

<!--Spring JmsTemplate 的消息生產者 end-->

3.生產者編程:

1.在消息生產者配置的基礎上,配置了一個jmsTemplate模板,我們可以使用:

// 注入queue消息模板

@Autowired

@Qualifier("jmsQueueTemplate")

private JmsTemplate jmsQueueTemplate;

注入到我們的程序中,然後調用send方法,向activeMQ中生產消息:

 

// 調用MQ服務,發送短信驗證碼

jmsQueueTemplate.send("bos_sms", new MessageCreator() {

@Override

public Message createMessage(Session session) throws JMSException {

MapMessage mapMessage = session.createMapMessage();

mapMessage.setString("telephone", model.getTelephone());

mapMessage.setString("checkCode", checkCode);

return mapMessage;

}

});

簡單解釋一下: send(消息名稱, 消息內容);

這個地方相當複雜:利用了兩個不容易理解的知識點: 我們簡單聊聊:

  1. 第一個問題:   jmsQueueTemplate 的Send()方法需要 MessageCreator 的createMessage()方法創建的消息內容,但是 MessageCreator 創建消息時需要 session,但是它卻沒有; 然而  jmsQueueTemplate  的execute()方法 卻可以獲得session , 所以 jmsQueueTemplate 對 MessageCreator 說:你先過來,然後我給你弄個session , 然後你給我弄message, 這裏邊體現的是, 接口作爲參數時,實現了主調方法的資源對接口中的方法的共享, 這裏主調方法是 send ,它可以想辦法拿到 session,然後 它把session共享給了 createMessage()方法;

如果說一般數據類型數據做爲形參,主調方法是爲了獲取實參的值,

那麼接口作爲形參時,主調方法是爲了獲得接口的方法, 還有一點附帶效果:傳入的接口中的方法可以共享主調方法的參數訪問權限(就是主調方法可以用的參數,接口中的方法也可以用;)

  1. 第二個問題: send 發送的消息內容是不固定的(有:1.MapMessage;2.ByteMessage;3.ObjectMessage;4.StreamMessage;5.TextMessage),也就是說 創建消息的方法體是不固定的,那麼是如何實現的呢? 用接口作爲參數傳入,由用戶動態定義方法的實現;

如果說我們在方法中調用類的靜態方法,是將一段固定代碼插入到主調方法中;

那麼對接口方法的調用,就是將一段動態代碼插入到主調方法中;

4.生產者總結:

ActiveMQ 的生產者:

廠商的 ActiveMQConnectionFactory 注入到 ------>Spring的  CachingConnectionFactory ------>注入到 Spring的 JmsTemplate ; 配置提供了這個模板對象之後,我們就可以在java代碼中注入這個對象,進行消息的創建;

5.消費者配置:

消費者要從ActiveMQ中拿消息, 肯定是要連接ActiveMQ服務器的,所以基礎連接配置,消費者配置中也需要一份,我們假設消費者配置中,已經配置好了基礎連接; 那麼這個時候已經可以拿到 CachingConnectionFactory , 這意味着我們已經可以通過這個連接工廠獲得與ActiveMQ的連接了; 如何完成消費呢? 首先編寫一個類實現 MessageListener 接口 ,然後將這個類註冊到消息監聽器容器中; 這裏說明一點,類實現了 MessageListener 接口本質上是爲了讓這個類實現監聽器應該具有的方法, 然而並沒有真正監聽ActiveMQ中的消息,這個時候需要配置到消息監聽器的容器(listener-container)中才能生效; 而這個(listener-container) 到底如何工作的呢? 我們來看看這個,消費者配置:

<!-- 定義Queue監聽器 -->

<jms:listener-container destination-type="queue" container-type="default"

connection-factory="connectionFactory" acknowledge="auto">

<!-- 默認註冊bean名稱,應該是類名首字母小寫  -->

<jms:listener destination="bos_sms" ref="smsConsumer"/>

</jms:listener-container>

<!-- 定義Topic監聽器 -->

<!--  <jms:listener-container destination-type="topic" container-type="default"

connection-factory="connectionFactory" acknowledge="auto">

<jms:listener destination="spring_topic" ref="topicConsumer1"/>

<jms:listener destination="spring_topic" ref="topicConsumer2"/>

</jms:listener-container> -->

我們可以看到:在消息監聽容器中,注入了兩個參數:

connection-factory="connectionFactory"

這個是配置了連接工廠, 是獲得與ActiveMQ服務器連接的;

<jms:listener destination="bos_sms" ref="smsConsumer"/>

這個是配置了監聽的消息目標:   destination="bos_sms"

(監聽者)消費者: ref="smsConsumer"

6.消費者編程:

(監聽者)消費者 本身是一個類,實現了 MessageListener 接口:

@Service("smsConsumer")

public class SmsConsumer implements MessageListener {

@Override

public void onMessage(Message message) {

MapMessage mapMessage = (MapMessage) message;

String telephone = null;

String checkCode = null;

try {

telephone = mapMessage.getString("telephone");

checkCode = mapMessage.getString("checkCode");

} catch (JMSException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

// 用輸出語句代替短信發送

System.out.println(telephone+" 的驗證碼是 : "+checkCode);

}

}

7.消費者總結:

其實消費者無非就是從ActiveMQ中獲得獲得消息, 那麼首先要獲得與ActiveMQ的連接,這個是通過基礎配置完成的, 連接以後要從裏邊拿消息呀,這個地方是在配置文件中配置一個監聽器容器, 將連接工廠和監聽器(其實就是一個實現了MessageListener的java類) 注入到這個監聽器中,這個時候就相當於通過監聽器容器,將監聽器和ActiveMQ建立了聯繫;

=================以上ActiveMQ == 以下 Quartz=====================

4.Quartz的配置:

0.框架知識概述:

Quartz是一個定時任務調度框架, 它關心的只要兩件事情:

  1. 要做什麼事情---->jobDetail(即任務詳情)
  2. 什麼時候做,頻率是什麼---->SimpleTrigger(依據時間)/CronTriggerFactoryBean(依據日曆) 即:任務執行策略;

Ps:

  1. 任務調度員scheduler,這個是將 jobDetail 和 SimpleTrigger 進行組合,生成一個日程,
  2. 另外還有一點要說明一下,在實際生產中,我們 jobDetail(即任務詳情)可能並不在Spring的管理之中, 但是, jobDetail(即任務詳情) 卻需要@autowired 被Spring管理的Service 或者其他bean, 這就違背了Spring規定:一個對象要想被注入對象,必須自己在Spring 管理之中,這個時候該怎麼解決呢, 我們知道,  Struts2與Spring整合時, action 沒有被Spring管理,卻可以注入被Spring管理的Service, 這裏我們使用同樣的方法解決這個問題,那就是創建了一個可以使 我們的 jobDetail 具有可以自動注入功能的工廠類 JobFactory ;我們在實際配置中是將 jobDetail 注入 SimpleTrigger ,再將 SimpleTrigger 注入 SchedulerFactoryBean ,那麼,此時我們將 JobFactory 注入到 SchedulerFactoryBean 中,那麼創建出來的 jobDetail 就具有了自動注入的功能; 問題得以解決;
  1. JobDetailFactoryBean配置:

JobDetailFactoryBean 是job的工廠,我們在裏邊注入我們的job類對象, 下面的配置中job並不在Spring管理中;

<bean id="promotionJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">

<property name="jobClass" value="cn.itcast.bos.quartz.PromotionJob"></property>

</bean>

  1. Job類編寫:

public class PromotionJob implements Job{

@Autowired

private PromotionService promotionService;

@Override

public void execute(JobExecutionContext context)

throws JobExecutionException {

//每分鐘執行一次,當前時間大於promotion數據表中的endDate ,活動已經過期,設置status='2'

promotionService.updateStatus(new Date());

}

}

  1. SimpleTriggerFactoryBean 配置:

將JobDetailFactoryBean 注入到 SimpleTriggerFactoryBean中:

<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">

<property name="jobDetail" ref="promotionJob"></property>

<property name="startDelay" value="0"></property>

<property name="repeatInterval" value="10000"></property>

</bean>

  1. SchedulerFactoryBean的配置:

將 SimpleTriggerFactoryBean 注入到 SchedulerFactoryBean中,同時還注入了一個 jobFactory這個jobFactory 注入的目的是是爲了讓我們的Job具有Spring自動注入功能;

<bean id="" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

<property name="jobFactory" ref="jobFactory"></property>

<property name="triggers">

<list>

<ref bean="simpleTrigger"/>

</list>

</property>

</bean>

  1. 附上 jobFactory的代碼:

@Service("jobFactory")

public class JobFactory extends AdaptableJobFactory {

@Autowired

private AutowireCapableBeanFactory capableBeanFactory;

@Override

protected Object createJobInstance(TriggerFiredBundle bundle)

throws Exception {

Object jobInstance = super.createJobInstance(bundle);

capableBeanFactory.autowireBean(jobInstance);

return jobInstance;

}

}

5.redis配置:

Redis是一個內存數據庫,由於存取速度非常快,往往用作緩存; 作爲一個數據庫, 無非就是考慮兩個問題:

  1. 怎麼連接這個數據庫,
  2. 怎麼操作這個數據庫;
  1. 配置連接池基本參數:

<!-- jedis 連接池配置 -->

<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">  

<property name="maxIdle" value="300" />        

<property name="maxWaitMillis" value="3000" />  

<property name="testOnBorrow" value="true" />  

</bean>  

  1. 配置連接工廠:

<!-- jedis 連接工廠 -->

<bean id="redisConnectionFactory"  

class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"  

p:host-name="localhost" p:port="6379" p:pool-config-ref="poolConfig"  

p:database="0" />  

  1. 配置模板:

<!-- spring data 提供 redis模板  -->

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">  

<property name="connectionFactory" ref="redisConnectionFactory" />

<!-- 如果不指定 Serializer   -->

<property name="keySerializer">

<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />

</property>

<property name="valueSerializer">

<bean class="org.springframework.data.redis.serializer.StringRedisSerializer">

</bean>

</property>

</bean>  

  1. Java代碼編寫示例:

// 2.將激活碼保存到redis中 可以設置存貨時間;

redisTemplate.opsForValue().set(model.getTelephone(), activeCode, 24, TimeUnit.HOURS);

6.持久層框架配置套路總結:

其實:持久層無非做了兩件事: 1.連接數據庫, 2操作數據庫 ;圍繞這兩件事每個框架都各有千秋,但是它們與Spring整合時的配置應該是有一些套路的:

1 . Spring 的JdbcTemplate

這個類簡化了JDBC操作,

它的基本操作:   update(sql語句, 參數);  query(sql語句, 參數);

操作流程如下:

  1. 配置驅動連接池 (可以用默認的,也可以單獨配比如C3P0連接池),屬性注入連接參數: driven,  url ,  username ,  password
  2. 配置 JdbcTemplate
  3. 我們可以在java類中直接注入  JdbcTemplate  進行CRUD操作;

2.hibernate:

  這是一個orm框架,通過映射文件,實現了對數據庫表的操作 到 對類的對象操作的轉化

操作流程如下:

  1. 將基本連接參數分離成一個.properties文件
  2. 在application.xml中引入.properties文件
  3. 配置連接池 (注入連接參數)
  4. 配置 LocalSessionFactory (注入1.連接池; 2.數據庫基本配置; 3.映射文件位置 )
  5. 編寫dao 繼承 HibernateDaoSupport類 並在
  6. 配置dao (注入sessionFactory, 本質上是注入到HibernateDaoSupport 中) 這樣在dao中就可以獲得: hibernateTemplate 模板對象;
  7. 利用模板對象進行CRUD操作,這個時候操作的,這個模板對象也是簡化hibernate數據訪問操作;

3.SpringDataJPA

1. 將基本連接參數分離成一個.properties文件

2. 在application.xml中引入.properties文件

3. 配置連接池 (注入連接參數)

4. 配置LocalContainerEntityManagerFactoryBean

注入 : 1.連接池;  2.domain掃描包路徑(相當於映射文件配置);  3.持久化提供者; 4.其他數據庫基本配置;

<property name="dataSource" ref="dataSource" />

<property name="packagesToScan" value="cn.itcast.bos.domain" />

<property name="persistenceProvider">

<bean class="org.hibernate.jpa.HibernatePersistenceProvider" />

</property>

...

5. Jpa掃描dao; 這一步等價於hibernate中的 dao配置,hibernate中是給dao中注入sessionFactory,使到可以獲得hibernateTemplate模板, 這個地方 通過掃描dao的方式,在獲得dao對象時通過AOP技術提供給我們默認的dao實現;

<jpa:repositories base-package="cn.itcast.bos.dao" />

 

4.redis

1.配置連接池 JedisPoolConfig

2.配置連接工廠 JedisConnectionFactory

3.配置模板 RedisTemplate

4.java代碼中操作:

redisTemplate.opsForValue().set(model.getTelephone(), activeCode, 24, TimeUnit.HOURS);

 

 

5.小結:

通過比較持久層這個幾個配置,我們可以看出來,Spring在整個各種框架是,基本套路也就是:

  1. 配置連接參數, 2.配置連接池, 3.配置連接工廠 4.配置模板;

 

相比之下: SpringDataJPA做的事情更多一些,它沒有直接提供給你一個模板,而是編寫了一個默認實現,你只要讓你的dao實現了JPARepository / JpaSpecificationExecutor , 在配上 jpa掃描:

<jpa:repositories base-package="cn.itcast.bos.dao" />

在你注入這個包下的對象時,它就會判斷你是否繼承了 JPARepository / JpaSpecificationExecutor 這些接口,如果繼承了,那麼它會利用AOP返給你一個默認實現的類,而在這個類中,已經給我們默認實現了一些CRUD常用操作,所以避免了常用CRUD操作的方法編寫;

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章