Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 在线欧美激情,视频一区二区在线,www亚洲国产

          整合營銷服務商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          各種配置文件總結

          各種配置文件總結

          . Spring Data JPA 配置:

          0.框架知識概述:

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

          1. 連接數(shù)據(jù)庫(比如 JDBD連接數(shù)據(jù)庫) 2.操作數(shù)據(jù)庫(比如 sql 操作數(shù)據(jù)庫);
          2. 連接數(shù)據(jù)庫:
          3. 配置參數(shù)抽取: 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 配置:
          2. 數(shù)據(jù)庫連接池配置: 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 ,這就相當于是用連接把實體類與數(shù)據(jù)庫表建立了聯(lián)系, [這里說明一點:實體和表之間的準確對應關系是依賴實體類中的注解來準確定位的] 這種聯(lián)系是非常緊密的,實體對象屬性值的變化直接會反映到數(shù)據(jù)庫表中, 而JPA作為接口規(guī)范,這里選擇 hibernate作為持久化提供者; 然后就是一些數(shù)據(jù)庫的基本配置了;)

          <!-- 整合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.操作數(shù)據(jù)庫:

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

          這里說明一點: dao的操作能被識別是CRUD的哪種操作, 至于操作哪個表, 是由在接口創(chuàng)建時傳入的泛型參數(shù)確定的, 傳入了一個泛型類,這個類代表著某張表; 簡而言之:dao描述了兩個問題: 1.我要執(zhí)行什么操作, 2.我要操作那張表;

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

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

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

          1. 配置事務管理器:

          (JDBC事務管理的本質(zhì),是對Session的管理, 那么這里配置了事務管理器, 就相當于指明了由誰來管理事務, 而同時屬性注入了 entityManagerFactory 實體管理者工廠,這就相當于將數(shù)據(jù)庫操作中的session交給了事務管理器,也就容易實現(xiàn)事務的管理了)

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

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

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

          </bean>

          1. 配置”事務注解驅(qū)動”

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

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

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

          4.Spring Data JPA 配置小結:

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

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

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

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

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

          @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 ,那么類的創(chuàng)建,準確來說是Service類的創(chuàng)建,也是由Spring來創(chuàng)建, 根據(jù)Spring創(chuàng)建bean的生命周期方法的執(zhí)行流程,我們知道,后處理bean中的方法執(zhí)行時機是在我們獲得bean對象之前,那么,后處理bean會利用AOP思想,在我們獲得的Service對象的方法執(zhí)行開始都加上session的事務開啟,在方法執(zhí)行末尾加上session的事務提交,和事務回滾,那么在我們拿到IOC 容器給我們創(chuàng)建的bean時,這個bean就是在事務管理之中的bean了; 這就完成了事務管理;

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

          1. WebService的配置:

          0.框架知識概述:

          (WebService 按目前使用來看就是提供了跨服務器遠程數(shù)據(jù)獲取的一種方式, 那我們只會關心兩個問題: 1. 遠程服務的創(chuàng)建與發(fā)布, 2,本地對遠程服務的訪問與數(shù)據(jù)接收; 其實遠程服務的創(chuàng)建,就是一個service接口 中方法訪問路徑,訪問方式,接收數(shù)據(jù)格式,返回數(shù)據(jù)格式的聲明, 至于服務的發(fā)布其實是交給了配置文件; 至于本地客戶端可能只需要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請求的基礎上,它會根據(jù)請求的url 去尋找對應的Service , 那么到哪里去尋找呢? 當然是到已經(jīng)發(fā)布到服務器中的Service中去找, 那么怎么才算是發(fā)布到服務器中了呢? 這里我們是通過在 .xml配置文件來實現(xiàn)發(fā)布的:

          比如下面配置 是將 PromotionServiceImpl 發(fā)布到服務器中

          <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接口中方法聲明---------------------------------------

          // 根據(jù)page和rows 返回分頁數(shù)據(jù)

          @Path("/pageQuery")

          @GET

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

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

          @QueryParam("rows") int rows);

          --------------------------------下面附上 Service實現(xiàn)編寫示例---------------------------------------

          @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.服務端配置小結:

          其實以上已經(jīng)說明了Service 接口編寫, Service接口實現(xiàn)編寫, Service服務在服務器端發(fā)布, 以及服務器端對 WebService 請求的攔截;

          3.客戶端請求操作:

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

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

          public String pageQuery() {

          // 基于WebService 獲取 bos_management的 活動列表 數(shù)據(jù)信息

          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();發(fā)起請求-------->服務端 web.xml配置 CXFServlet 攔截所有 /services 開頭請求--------> applicationContext-webService.xml 發(fā)布服務-------> Service接口中的具體方法, 聲明服務訪問方式,-------> Service實現(xiàn)類中 提供了服務真正的操作內(nèi)容;

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

          3.ActiveMQ 的配置:

          0.框架知識概述:

          ActiveMQ 是JMS java消息服務的規(guī)范的實現(xiàn): 個人感覺它是一個服務器,有著自己的訪問端口,但是它的工作卻是存儲消息, 又很像一個存放消息的數(shù)據(jù)庫,所以在和 Spring整合時特像一個數(shù)據(jù)庫: 其實:ActiveMQ 的事情也是兩件:1.給生產(chǎn)者提供存放消息的入口, 2.給消費者提供消費消息的入口:

          1. 基礎連接配置:

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

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

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

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

          <!-- 如果連接網(wǎng)絡:tcp://ip:61616;未連接網(wǎng)絡: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對應真實的可以產(chǎn)生JMS Connection的ConnectionFactory -->

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

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

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

          <!-- Session緩存數(shù)量 -->

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

          </bean>

          1. 基礎配置小結

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

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

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

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

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

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

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

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

          <constructor-arg ref="mqConnectionFactory" />

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

          <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模型(發(fā)布/訂閱) -->

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

          </bean>

          <!--Spring JmsTemplate 的消息生產(chǎn)者 end-->

          3.生產(chǎn)者編程:

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

          // 注入queue消息模板

          @Autowired

          @Qualifier("jmsQueueTemplate")

          private JmsTemplate jmsQueueTemplate;

          注入到我們的程序中,然后調(diào)用send方法,向activeMQ中生產(chǎn)消息:

          // 調(diào)用MQ服務,發(fā)送短信驗證碼

          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(消息名稱, 消息創(chuàng)建接口);

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

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

          如果說一般數(shù)據(jù)類型數(shù)據(jù)做為形參,主調(diào)方法是為了獲取實參的值,

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

          1. 第二個問題: send 發(fā)送的消息內(nèi)容是不固定的(有:1.MapMessage;2.ByteMessage;3.ObjectMessage;4.StreamMessage;5.TextMessage),也就是說 創(chuàng)建消息的方法體是不固定的,那么是如何實現(xiàn)的呢? 用接口作為參數(shù)傳入,由用戶動態(tài)定義方法的實現(xiàn);

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

          那么對接口方法的調(diào)用,就是將一段動態(tài)代碼插入到主調(diào)方法中;

          4.生產(chǎn)者總結:

          ActiveMQ 的生產(chǎn)者:

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

          5.消費者配置:

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

          <!-- 定義Queue監(jiān)聽器 -->

          <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監(jiān)聽器 -->

          <!-- <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> -->

          我們可以看到:在消息監(jiān)聽容器中,注入了兩個參數(shù):

          connection-factory="connectionFactory"

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

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

          這個是配置了監(jiān)聽的消息目標: destination="bos_sms"

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

          6.消費者編程:

          (監(jiān)聽者)消費者 本身是一個類,實現(xiàn)了 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();

          }

          // 用輸出語句代替短信發(fā)送

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

          }

          }

          7.消費者總結:

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

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

          4.Quartz的配置:

          0.框架知識概述:

          Quartz是一個定時任務調(diào)度框架, 它關心的只有兩件事情:

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

          Ps:

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

          //每分鐘執(zhí)行一次,當前時間大于promotion數(shù)據(jù)表中的endDate ,活動已經(jīng)過期,設置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是一個內(nèi)存數(shù)據(jù)庫,由于存取速度非常快,往往用作緩存; 作為一個數(shù)據(jù)庫, 無非就是考慮兩個問題:

          1. 怎么連接這個數(shù)據(jù)庫,
          2. 怎么操作這個數(shù)據(jù)庫;
          3. 配置連接池基本參數(shù):

          <!-- 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.SpringDataElasticSearch配置:

          0.框架知識概述:

          簡化操作ElasticSearch的技術: 是SpringData 項目下的一個子項目,為了整合 ElasticSearch ; 經(jīng)過一系列配置,提供了類似SpringDataJPA的操作模式;

          ElasticSearch是一個全文搜索服務器 , 但本質(zhì)上是一個索引庫: 它的一些基本概念和關系型數(shù)據(jù)庫概念對應關系如下:

          索引(index)------->表(table)

          文檔(document)------->一條數(shù)據(jù)實體(entity)

          域(filed) --------> 字段(field)

          作為一個數(shù)據(jù)庫,我們還是關心兩個老問題:1.怎么連接上這個數(shù)據(jù)庫, 2.怎么操作這個數(shù)據(jù)庫;

          1. 連接ElasticSearch:

          1.配置客戶端 client

          <!-- 配置elasticsearch 連接 其實這個地方配置的是客戶端 :transportclient -->

          <elasticsearch:transport-client id="client" cluster-nodes="localhost:9300" />

          2.配置模板對象: 注入client對象

          <!-- spring data elasticsearch DAO 必須依賴 elasticsearchTemplate -->

          <bean id="elasticsearchTemplate"

          class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">

          <constructor-arg name="client" ref="client" />

          </bean>

          3.實體類要配置映射

          這個映射與hibernate中的對象映射有些類似,但是還有不同,這個映射配置, 其實配置了實體的存儲策略(就想當于指明關系數(shù)據(jù)庫的表結構怎么建),檢索策略,分詞策略,等;

          4.連接配置小結:

          配置客戶端:client ------>注入 elasticsearchTemplate ----->實體配置映射注解;

          這個地方實體映射配置某種程度上說是一個 單純的映射配置的載體; 模板對象讀取這個類時,可以讀取這個對象中的映射文件;

          1. 操作ElasticSearch:

          配置掃描dao , 并且我們的dao繼承了 ElasticSearchRepository 接口,這樣我們在

          @autowired dao實現(xiàn)時,就會注入框架默認的實現(xiàn);

          <!-- 掃描DAO包 自動創(chuàng)建實現(xiàn) -->

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

          3.ElasticSearch 配置小結:

          我們連接ElasticSearch 是通過配置客戶端操作對象 transportclient , 其實拿著這個client已經(jīng)可以操作 ElasticSearch 了,但是 我們又對這個client進行了一次封裝,封裝成了一個 template (模板), 這個模板已經(jīng)可以完成了一些基本操作了, 然而在此時,我們沒有止步,而是又做了一層封裝, 封裝成了一個默認實現(xiàn),我們編寫一個dao 繼承 ElasticsearchRepository 這個接口,然后AOP就會給我們返回一個默認實現(xiàn)的 repository,這個repository 實現(xiàn)了基本增刪改, 規(guī)范的find查詢方法,等等 這點有點兒類似SpringDataJPA ;

          7.shiro配置:

          Shiro是一個權限控制框架:

          權限控制流程: applicationCode -----> Subject------> ShiroSecurityManager----->Realm ;

          其實權限控制問題簡單來說就是: 哪些user 可以訪問哪些 url的問題;

          1.粗粒度url權限驗證流程:

          request 請求發(fā)出--->web.xml中的DelegatingFilterProxy 代理過濾器過濾到請求----> 交給applicationContext.xml 中的真正的過濾器 ShiroFilterFactoryBean----> 過濾器將請求交給 "安全管理器" securityManager ----->"安管"讀取過濾器中的 "資源與訪問權限對應清單" filterChainDefinitions ----->"安管"找到request要訪問的資源需要的權限:permission1 ---->

          "安管" 調(diào)用 "小弟" realm 的 doGetAuthorizationInfo()方法,獲得當前用戶所持有的權限: permission2 ---->此時:"安管"已經(jīng)從過濾器中拿到 1. 要訪問的資源需要的權限:permission1 2. 前用戶所持有的權限: permission2 ,所以"安管"可以很輕松地將兩個權限做比較,如果匹配,那么就允許用戶訪問資源,如果不匹配,則拒絕訪問該資源,并跳轉(zhuǎn)到?jīng)]有權限訪問的頁面;

          2.細粒度方法級別權限驗證流程:

          request請求發(fā)出----> 調(diào)用 save()方法----> Spring 嘗試利用 IOC 創(chuàng)建cglib 動態(tài)代理對象,卻發(fā)現(xiàn)目標類 的save()方法上有shiro注解,然后就利用AOP 在代理類的save方法上加上前置通知: AuthorizationAttributeSourceAdvisor 來讀取save()方法上的 shiro注解,并將結果交給"安管"----->securityManager 獲得 save()方法訪問應具備的權限 -----> 調(diào)用realm的doGetAuthorizationInfo()方法,來獲得當前用戶所持有的權限, 然后安管自己會對兩個權限作對比,判定是否可以訪問資源...;

          3.兩種權限驗證方式對比分析:

          粗粒度url權限控制 與 細粒度方法級別權限控制 對比分析:

          粗粒度url權限控制

          細粒度方法級別權限控制

          資源控制者

          securityManager

          securityManager

          資源訪問所需權限獲取來源

          過濾器 shiroFilter 中的屬性配置

          Spring框架 (IOC和AOP共同作用)從方法的注解讀取

          當前用戶訪問權限獲取來源

          小弟: realm

          小弟:realm

          權限不足時處理方式

          過濾器配置相應友好提示頁面

          拋出相應異常給方法調(diào)用者;

          1. 緩存框架Ehcache 的配置

          0.框架知識概述:

          當我們用Shiro做權限管理的時候,我們每一次對資源進行訪問時我們的 “安全管理器” securityManager 會對當前用戶進行權限的授權信息獲取, 如果每次獲取當前用戶的授權信息都到數(shù)據(jù)庫中查詢,這樣無疑是降低了資源獲取的速度,用戶體驗不好,所以這種情況,我們必然要對用戶權限信息進行緩存處理;

          Flag:緩存技術不一定用在權限管理,但權限管理一定會用到緩存;

          1. 復制自帶配置文件 ehcache-failsafe.xml

          Ehcache 的jar包下有默認配置文件,我們將它復制到與applicationContext.xml 同級目錄下;

          我們在這個配置文件里邊創(chuàng)建自定義的緩存空間;

          1. Spring整合(管理)Ehcache

          Ehcache 的 EhCacheManager “緩存管理器” 交給Spring的EhCacheManagerFactoryBean “緩存管理器工廠bean” 來管理;

          至此, ehcache已經(jīng)在Spring的管理之中了;

          <!-- Ehcache配置 (ehcache的 "緩存管理器" 納入Spring管理) -->

          <bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">

          <property name="configLocation" value="classpath:ehcache.xml"></property>

          </bean>

          1. Ehcache 對Shiro 的權限數(shù)據(jù)進行數(shù)據(jù)緩存
          2. Shiro 整合 Ehcache

          Ehcache 底層是Map結構實現(xiàn),所以Shiro要對Ehcache 的緩存管理器再做一層封裝,指明什么作為key,什么作為value ,這個封裝類就是: EhCacheManager ,我們將ehcache的 "緩存管理器" 屬性注入到shiro 的 EhCacheManager :

          <!-- shiro配置 (將ehcache的 "緩存管理器" 屬性注入到shiro) -->

          <!-- ehcache 底層是Map實現(xiàn),所以Shiro要對ehcache的緩存管理器在做一層封裝,指明什么作為key,什么作為value -->

          <bean id="shiroEhCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">

          <property name="cacheManager" ref="ehCacheManager"></property>

          </bean>

          1. Shiro “安全管理器” 獲得 “Ehcache緩存管理器”

          根據(jù)Shiro權限驗證執(zhí)行流程: 應用程序代碼------> subject ------> securityManager----->

          Realm ------> 訪問安全數(shù)據(jù) ;

          <!-- 安全管理器 -->

          <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

          <property name="realm" ref="bosRealm"></property>

          <property name="cacheManager" ref="shiroEhCacheManager"></property>

          </bean>

          上邊配置的結果是: “安全管理器” 獲得了緩存操作權限; 這樣它的小弟 realm 就可以向 “安全管理器” 申請一個緩存空間, 什么意思呢? 就是小弟realm說:你把 “bos” 這個緩存區(qū)給我,以后你找我要數(shù)據(jù),你先到這個緩存區(qū)看看有沒有,如果沒有,我再去數(shù)據(jù)庫幫你找到,然后你要把數(shù)據(jù)放進去,下次不要找我要了;

          1. Reaml 指定將 哪些 數(shù)據(jù)存入 哪個 緩存區(qū)

          <!-- Realm配置, 指明將 "授權數(shù)據(jù)" 緩存到 "bos" 緩沖區(qū)-->

          <bean id="bosRealm" class="cn.itcast.bos.realm.BosRealm">

          <property name="authorizationCacheName" value="bos"></property>

          </bean>

          1. Ehcache對權限數(shù)據(jù)緩存的 配置流程總結:

          在Ehcache的 ehcache-failsafe.xml中自定義緩存區(qū) ------> Spring與Ehcache的整合類(EhCacheManagerFactoryBean)讀取配置文件 得到 ehCacheManager------> ehCacheManager

          注入到 Shiro的 shiroEhCacheManager ------> shiroEhCacheManager 注入到 “安全管理器” securityManager ------> Reaml 通過屬性配置 來 聲明要緩存數(shù)據(jù),以及要緩存的區(qū)域 (比如 bos) ;

          4. Ehcache對一般數(shù)據(jù)的緩存配置:

          1. Spring “緩存管理器” 封裝 Ehcache的 “緩存管理器”

          在Shiro 整合Ehcache時,有一個 shiroEhCacheManager 來管理 key-value的生成策略, 那么在對一般數(shù)據(jù)的緩存配置時,肯定是不能用這個緩存管理器了, 這個時候Spring 就出來說話了,他說 我定義一個 “緩存管理器” 來管理 一般數(shù)據(jù)的key-value的生成策略;

          <!-- Spring 封裝Ehcache的緩存管理器,它規(guī)范了普通數(shù)據(jù)緩存時的key-value 生成策略 -->

          <bean id="springCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">

          <property name="cacheManager" ref="ehCacheManager"/>

          </bean>

          這個緩存管理器一方面是獲得 Ehcache 的緩存管理器,擁有了緩存操作權限 ; 另一方面是提供了一些標簽,它可以解釋這些標簽,來執(zhí)行緩存操作 ;

          2.在Spring的配置文件中 激活spring 緩存注解

          目的就是讓Spring 能夠識別它管理的類中的緩存注解;

          <!-- 激活spring 緩存注解 -->

          <cache:annotation-driven cache-manager="springCacheManager"/>

          3.在被Spring管理的bean的方法上使用 @Cacheable() , @CacheEvict() :

          @Cacheable(value=”緩存區(qū)”) : 應用緩存, 對方法返回結果進行緩存, 這個注解多用在查詢方法上; 至于誰是key ,誰是value 由Spring的緩存管理器來負責; 如果被注解的方法有不同的 傳入?yún)?shù), 可在注解中使用SpEL (Spring表達式) 自定義key值;

          @CacheEvict (value=”緩存區(qū)”,allEntries=”true”): 清除緩存區(qū)的數(shù)據(jù), allEntries代表所有數(shù)據(jù);

          1. 緩存配置中的注意點:

          被緩存的對象數(shù)據(jù)對應的類要序列化 : implements Serializable ;

          1. Freemarker 模板引擎

          Struts2 默認是使用 Freemarker作為自定義標簽模板,所以項目導入了Struts2 就已經(jīng)導入了Freemarker的jar包;

          0.技術概述:

          Freemarker就是一個模板引擎,它類似我們之前學習的jsp; FreeMarker 它通過編寫一個模板文件,結合我們程序中的動態(tài)數(shù)據(jù),輸出標準的文本內(nèi)容,一般情況下我們用它來生成html文件比較多;

          簡單來說: 模板文件 + java數(shù)據(jù)對象==輸出 (任何格式文本)

          FreeMarker 模板文件,通常擴展名 .ftl (當然也可以用 .html / .jsp)

          我們編寫前,要安裝一個Freemarker的插件,安裝到eclipse ,這樣我們編輯時就會有提示; Freemarker 模板文件中的變量 跟EL 表達式一樣,都是 ${變量名}

          1. 編寫模板文件 promotion_detail.ftl

          <link rel="stylesheet" type="text/css" href="css/promotion_detail.css">

          <div class="container promotions" >

          <div class="col-md-2 prolist">

          <h5 class="title"><a href="#/promotion"><strong>返回促銷列表</strong></a></h5>

          <img src="images/pro.jpg" class="img-responsive">

          </div>

          <div class="col-md-10 procontent">

          <h5 class="title">${promotion.title}</h5>

          <div class="intro">

          <p>活動范圍: ${promotion.activeScope}</p>

          <p>活動時間: ${promotion.startDate?string("yyyy-MM-dd")} -

          ${promotion.endDate?string("yyyy-MM-dd")}</p>

          </div>

          <div class="partline clearfix"></div>

          <div class="promotionbox">

          ${promotion.description}

          </div>

          </div>

          </div>

          1. 編寫java代碼

          // 用面向?qū)ο笏枷?將配置文件目錄封裝為configuration對象

          Configuration configuration=new Configuration(

          Configuration.VERSION_2_3_22);

          configuration.setDirectoryForTemplateLoading(new File(

          ServletActionContext.getServletContext().getRealPath(

          "/WEB-INF/freemarker_templates")));

          // 用 configuration 獲取模板對象 template

          Template template=configuration

          .getTemplate("promotion_detail.ftl");

          // 動態(tài)數(shù)據(jù)

          Promotion promotion=WebClient

          .create(Constants.BOS_MANAGEMENT_URL

          + "/bos_management/services/promotionService/promotion/"

          + model.getId()).accept(MediaType.APPLICATION_JSON)

          .get(Promotion.class);

          //構造動態(tài)數(shù)據(jù) ()

          Map<String, Object> parameterMap=new HashMap<String, Object>();

          parameterMap.put("promotion", promotion);

          //使用模對象合并數(shù)據(jù) template 合并輸出

          /* @param dataModel the holder of the variables visible from the template (name-value pairs); usually a {@code Map<String, Object>} or a JavaBean (where the JavaBean properties will be the variables) */

          template.process(parameterMap, new OutputStreamWriter(

          new FileOutputStream(htmlFile), "utf-8"));

          模板對象 template 合并數(shù)據(jù)時,將數(shù)據(jù)模型數(shù)據(jù)dataModel 輸出到writer流中; 而這個dataModel 的數(shù)據(jù)類型一般是 Map<String, Object> , 當然也可以是 JavaBean ,這個 JavaBean 的屬性是模板中的變量; 另外要說一點,如果模板中有變量必須全部賦值, 如果存在一個沒有賦值, 好像會報錯;

          1. Spring與Mybatis整合配置

          PS: mybatis框架的特別之處是,它實現(xiàn)了sql語句與java代碼的分離,所以它要解決的核心問題是如何讓mapper.xml中的sql語句在數(shù)據(jù)庫操作時起作用;

          另外說明一點:

          在mybatis單獨使用時: mapper.xml-----> SqlMapConfig.xml ------> sqlSessionFactory ----->sqlSession , 所以這個時候 mapper.xml的引用在sqlSession中,因此 外置sql語句的調(diào)用是由sqlSession來完成的;

          在mybatis與spring整合時: SqlMapConfig.xml ----> sqlSessionFactory ----> MapperFactoryBean; 由于在mybatis與spring整合時,SqlMapConfig.xml是一個空的文件,所以里邊沒有mapper.xml的引用,所以沒有辦法使用里邊的sql,這個時候怎么解決這個問題呢? 通過一個強制要求: 映射文件(mapper.xml)必須與相應的接口同名且在同一個目錄下,這樣在創(chuàng)建代理時,在讀取接口的同時會在相同目錄下去尋找映射文件,這樣就同時利用接口和映射文件生成了代理對象;

          1. 連接數(shù)據(jù)庫
          2. 數(shù)據(jù)庫連接參數(shù)抽取: db.properties

          jdbc.driver=com.mysql.jdbc.Driver

          jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8

          jdbc.username=root

          jdbc.password=123

          1. Spring核心配置文件applicationContext.xml 中加載db.properties并配置連接池BasicDataSource

          1.簡單說明:

          連接池的作用是提供連接,并且不用反復創(chuàng)建銷毀數(shù)據(jù)庫連接;

          2.配置內(nèi)容:

          <!-- 加載屬性配置文件 -->

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

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

          <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"

          destroy-method="close">

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

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

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

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

          <property name="maxActive" value="10" />

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

          </bean>

          1. 配置Spring與Mybatis整合類 org.mybatis.spring.SqlSessionFactoryBean

          1.簡單說明:

          sqlSessionFactory 跟hibernate的SessionFactory , SpringDataJPA的EntityManagerFactory 的功能非常類似:

          1.注入連接池,獲得了連接數(shù)據(jù)庫的能力;

          2. 注入了映射配置文件位置; 區(qū)別在于:hibernate的映射配置文件是配置了實體與表之間的映射,最后干脆通過注解,將映射配置放到了實體類中,最后sql語句(或者hql)的編寫就寫到dao中了; 然后就是SpringDataJPA, 它是在Hibernate基礎之上,將一部分sql語句做了封裝實現(xiàn),這樣我們在對數(shù)據(jù)庫進行一些簡單操作的時候,我們可以直接通過調(diào)用一些方法就可以了,等于是幫我們已經(jīng)完成了一些簡單的CRUD操作; 但是一些復雜的查詢操作,我們還是需要自己在 Dao中編寫查詢語句(hql或者是sql),不論是hibernate還是 SpringDataJPA 都沒有將Sql語句與java 代碼分離, 而mybatis卻做了這一點: mybatis的映射配置文件中有三部分: 1.輸入映射; 2.輸出映射;3. sql語句映射; 其中輸入輸出映射完成了類似orm映射的功能,完成類與表的對應; 而sql語句映射其實是提供了一些固定的sql操作,然后我們通過:

          1. sql映射的namespace 使用Dao接口的 全限定名

          2.sql映射的 statementId 與Dao接口的方法名一致

          3.sql映射的parameterType與Dao中方法的參數(shù)類型一致

          4.sql映射的resultType與Dao中方法的返回值類型一致

          以上四點約定,我們的sql映射實際上已經(jīng)成為以后Mybatis使用Mapper代理方式時,Spring創(chuàng)建代理的依據(jù); 所以說某種程度上說mapper映射文件中的sql映射部分可以視作是Dao接口的實現(xiàn)類; 這樣其實實現(xiàn)了 “實現(xiàn)類”到”映射文件”的轉(zhuǎn)變( java代碼----->xml配置的轉(zhuǎn)變), 將sql語句從java 代碼中抽離出來了;

          2.配置內(nèi)容:

          <!-- 配置sqlSessionFactoryBean -->

          <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

          <!-- 注入連接池 -->

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

          <!-- 加載mybatis 核心配置文件 -->

          <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"/>

          </bean>

          1. 操作數(shù)據(jù)庫
          2. 簡單說明:

          我在前面總結持久層框架的時候喜歡將配置分為兩部分:

          1. 連接數(shù)據(jù)庫 : 得到SessionFactory
          2. 操作數(shù)據(jù)庫 : 將SessionFactory 與dao融合;

          2.配置內(nèi)容:

          <!-- 第一種方式: 通過設置mapper接口 ; 缺點:一次只能配置一個接口-->

          <!-- <bean class="org.mybatis.spring.mapper.MapperFactoryBean<T>">

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

          <property name="mapperInterface" value="cn.itheima.mybatis.mapper.UserMapper"></property>

          </bean> -->

          <!-- 第二種方式: 通過對mapper包掃描;

          優(yōu)點:1.可以對mapper包下的所有接口完成代理; 2.會自動注入 sqlSessionFactory -->

          <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

          <property name="basePackage" value="cn.itheima.mybatis.mapper"/>

          </bean>

          上邊兩種配置都可以完成 sqlSessionFactory 與Dao的融合,但是第二種更有優(yōu)勢: 我們簡單分析一下: 它是通過掃描包,然后找到包下的接口,然后讀取到包下同名的mapper.xml映射文件,然后根據(jù) 接口和映射文件創(chuàng)建 接口實現(xiàn)類對象;

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

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

          1 . Spring 的JdbcTemplate

          這個類簡化了JDBC操作,

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

          操作流程如下:

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

          2.hibernate:

          這是一個orm框架,通過映射文件,實現(xiàn)了對數(shù)據(jù)庫表的操作 到 對類的對象操作的轉(zhuǎn)化

          操作流程如下:

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

          3.SpringDataJPA

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

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

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

          4. 配置LocalContainerEntityManagerFactoryBean

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

          <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實現(xiàn);

          <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. 配置連接參數(shù), 2.配置連接池, 3.配置連接工廠 4.配置模板;

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

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

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

          . 介紹

          1.1 介紹

          福哥今天帶著大家了解一下SpringBoot如何處理靜態(tài)資源文件的。靜態(tài)資源文件包括CSS樣式表、圖片文件(jpg、png、gif)、JavaScript腳本以及各種媒體、壓縮包等等內(nèi)容,總結一句話就是非配置文件、非Java的文件。

          靜態(tài)資源文件是不需要經(jīng)過編譯、執(zhí)行的,最好的處理方式是通過Nginx直接處理。但是我們在開發(fā)調(diào)試階段是沒有Nginx服務器的,只能通過Tomcat進行處理,這時候就需要了解一下如何在SpringBoot項目里面處理這些靜態(tài)的資源文件了。

          2. 目錄

          2.1 目錄

          SpringBoot給我們預留了資源文件的根目錄,就是main下面的resources,和java在同一目錄下。然后,如果我們在resources下面建立staitc、public、resources這幾個目錄的話,最后都會被SpringBoot當作靜態(tài)目錄使用。

          2.2 優(yōu)先級

          如果我們在static、public、resources里面建立了同樣的目錄結構,放入了同名的文件,那么最后哪個目錄下面的文件會被使用呢?

          記住下面這個優(yōu)先級順序,就好辦了!

          resources > static > public

          雖然resources的優(yōu)先級是最高的,不過福哥還是推薦使用static這個目錄名稱,比較這個單詞更加符合我們放入的文件的意思嘛~~

          3. 測試

          index.ftl

          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>demo</title>
              <link type="text/css" href="/css/index.css" rel="stylesheet" />
              <script type="text/javascript" src="/js/index.js"></script>
          </head>
          <body>
          
          <h3>福哥的demo</h3>
          <p>
              這是福哥的一個demo項目,用來給大家做教程使用!
          </p>
          <span id="browser"></span><br />
          <span>http://demo.tongfu.net/</span>
          
          </body>
          </html>

          index.css

          body{
              font-size: 12px;
          }

          index.js

          document.onreadystatechange=function(){
              document.getElementById('browser').innerHTML = navigator.appName;
          };

          4. 認證

          如果我們的項目有認證設計,那么就需要針對靜態(tài)的資源文件進行“免認證”設置,這個可以通過antMatchers進行配置,可以通過“*”通配符進行批量設置。

          security
                  .csrf().disable()
          
                  .authorizeRequests()
          
                  .antMatchers("/css/*", "/images/*", "/js/*").permitAll()
          
                  .anyRequest()
                  .authenticated()
          
                  .and()
          
                  .httpBasic()
                  ;

          5. 總結

          今天福哥帶著童鞋們學習了如何在SpringBoot框架里面處理靜態(tài)資源文件。我們可以使用freemarker去處理頁面html,在html里面引用這些靜態(tài)資源文件,綜合這些就可以滿足web平臺的開發(fā)需求了!


          https://tongfu.net/home/35/blog/513605.html

          雖然現(xiàn)在流行前后端分離開發(fā)和部署,但是有時候還是需要用到服務端渲染頁面的。比如:需要考慮到SEO優(yōu)化等問題的時候,F(xiàn)reeMark其實還是很有作用的。本人的博客本來是用React開發(fā)的,但是后來發(fā)現(xiàn)搜索引擎難以收集由JS渲染的頁面,所以前段時間,是用jQuery+FreeMark重寫了我的博客前端頁面。感興趣的朋友,可以點擊下面的查看更多的鏈接跳轉(zhuǎn)至本人的博客。

          在springboot中,不推薦使用JSP(其實任何項目都不推薦使用JSP),而是推薦使用模板引擎,如FreeMark。其實使用模板引擎替代jsp的好處有很多,比如:FreeMark不需要便已成為class,避免了內(nèi)存溢出的可能性,等等。好處有很多,這里就不深入探討了。

          springboot引入FreeMark

          引入依賴:

          <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-freemarker</artifactId>
          </dependency>
          

          配置FreeMark:

          # freeMark config
          spring.freemarker.allow-request-override=false
          spring.freemarker.cache=true
          spring.freemarker.check-template-location=true
          spring.freemarker.charset=UTF-8
          spring.freemarker.content-type=text/html
          spring.freemarker.expose-request-attributes=false
          spring.freemarker.expose-session-attributes=false
          spring.freemarker.expose-spring-macro-helpers=false
          spring.freemarker.suffix=.ftl
          spring.freemarker.template-loader-path=classpath:/static/
          

          這里,我把freemark的路勁配置到了static目錄下。完成這些步驟,F(xiàn)reeMark已經(jīng)配置完成了。

          可以通過一個簡單的頁面來測試下freeMark。在static文件夾中創(chuàng)建index.ftl

          <!doctype html>
          <html lang="en">
          <head>
           <meta charset="UTF-8">
           <meta name="viewport"
           content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
           <meta http-equiv="X-UA-Compatible" content="ie=edge">
           <title>Freem測試</title>
          </head>
          <body>
          這是一個FreeMark。后臺傳過來的數(shù)據(jù):${data}
          </body>
          </html>
          

          這個freemark頁面,展示從controller傳過來的"data"。

          新建一個PageController.class

          @Controller
          public class PageController {
          ?
           @GetMapping(value="/")
           public String index(HttpServletRequest request){
           request.setAttribute("data","Hello World!!!");
           return "index";
           }
          ?
          }
          ?
          

          這里千萬別寫RestController,否則會報錯的。這里在request中,設置了data為Hello World!!!,啟動項目查看效果:

          這已經(jīng)表明,SpringBoot配置FreeMark已經(jīng)成功了。

          FreeMark常用用法

          取值

          ${user}
          如果需要取對象里的某個屬性,則使用"."即可
          ${user.name}
          

          遍歷

          <#list list as item>
           ${item.name}
          </#list>
          ?
          <#list ["星期一", "星期二", "星期三"] as day>
           ${day}
          </#list>
          

          條件

          <#if username=="boss">
           Hi boss!
          </#if>
          ?
          <#if username=="boss">
           Hi boss!
          <#else>
           Hi!
          </#if>
          

          設置默認值

          如果沒有默認值,F(xiàn)reeMark會報錯

          ${varname!default_value}
          

          日期格式化

          ${date?string("yyyy-MM-dd HH:mm:ss")}
          

          用法有很多,這里沒法一一列舉出來。只能列舉出比較常用的。這些東西沒必要去記住它,可以在需要的時候去查一下文檔即可。

          總結

          本文介紹了SpringBoot整合FreeMark的方法。雖然現(xiàn)在主流是前后端分離開發(fā)和部署,但是在某些時候,或者說一些小項目中,還是有可能用到后端渲染頁面的情況的。


          主站蜘蛛池模板: 天堂va在线高清一区| 88国产精品视频一区二区三区| 夜色福利一区二区三区| 色婷婷AV一区二区三区浪潮| 国产乱码精品一区二区三区麻豆| 日本不卡一区二区三区视频| 国产一区二区三区91| 在线播放精品一区二区啪视频| 色偷偷av一区二区三区| 国语精品一区二区三区| 亚洲爽爽一区二区三区| 国产乱码精品一区二区三区四川| 国模无码一区二区三区 | 国产精品自在拍一区二区不卡| 精品无码一区二区三区电影 | 亚洲av无码成人影院一区| 水蜜桃av无码一区二区| 无码人妻精品一区二区三区66| 中文字幕精品一区二区精品| 成人区精品人妻一区二区不卡| 色狠狠色噜噜Av天堂一区| 久久一区二区免费播放| 狠狠做深爱婷婷综合一区| 一区二区三区在线播放| 精品乱子伦一区二区三区高清免费播放 | 国产福利电影一区二区三区久久久久成人精品综合 | 免费高清av一区二区三区| 麻豆精品人妻一区二区三区蜜桃 | 亚洲一区二区三区成人网站| 国产精品揄拍一区二区久久| 日本一道高清一区二区三区| 无码丰满熟妇一区二区| 免费观看日本污污ww网站一区| 精品成人一区二区三区免费视频 | 亚洲一区二区精品视频| 日本一区二区不卡在线| 精品国产aⅴ无码一区二区| 午夜视频一区二区三区| 日本一区午夜艳熟免费| 亚洲午夜一区二区电影院| 精品国产亚洲一区二区三区在线观看|