1. Spring Data JPA 配置:
0.框架知识概述:
Spring Data JPA 是一个持久层的框架,而一个持久层框架所做的事情不过两件:
- 连接数据库(比如 JDBD连接数据库) 2.操作数据库(比如 sql 操作数据库);
- 连接数据库:
- 配置参数抽取: 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
- applicationContext-dataSource.xml 配置:
- 数据库连接池配置: 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>
- 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.操作数据库:
- 整合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>
- 配置”事务注解驱动”
(这样就可以识别 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 也给我们留了一个口子:
- 比如一些标准的操作:
- findById() , findByProvinceAndCityAndDistrict 等
- 更复杂的操作:
@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====================
- WebService的配置:
0.框架知识概述:
(WebService 按目前使用来看就是提供了跨服务器远程数据获取的一种方式, 那我们只会关心两个问题: 1. 远程服务的创建与发布, 2,本地对远程服务的访问与数据接收; 其实远程服务的创建,就是一个service接口 中方法访问路径,访问方式,接收数据格式,返回数据格式的声明, 至于服务的发布其实是交给了配置文件; 至于本地客户端可能只需要WebClient 加上一个正确格式的url就可以了)我们这里说一下 JAX-RS 的配置:
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步拦截到所有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.给消费者提供消费消息的入口:
- 基础连接配置:
无论是 “生产消息” 还是 “消费消息” :我们都要有基础的连接配置:
- 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>
- 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>
- 基础配置小结
不管我们用那种JMS产品,它都会提供一个连接工厂,而与Spring整合时,我们用 CachingConnectionFactory 将JMS服务厂商提供的连接工厂进行封装, 那么我们就可以不需要针对不同的 连接工厂操作了,只需要对同一个 CachingConnectionFactory 尽心操作,达到了解耦的目的; 流程如下:
JMS厂商提供ActiveMQ 提供 ActiveMQConnectionFactory 连接工厂------>Spring 提供 CachingConnectionFactory 缓存连接工厂 封装厂商提供的连接工厂
- 生产者配置:
- 这个消息生产者配置,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(消息名称, 消息内容);
这个地方相当复杂:利用了两个不容易理解的知识点: 我们简单聊聊:
- 第一个问题: jmsQueueTemplate 的Send()方法需要 MessageCreator 的createMessage()方法创建的消息内容,但是 MessageCreator 创建消息时需要 session,但是它却没有; 然而 jmsQueueTemplate 的execute()方法 却可以获得session , 所以 jmsQueueTemplate 对 MessageCreator 说:你先过来,然后我给你弄个session , 然后你给我弄message, 这里边体现的是, 接口作为参数时,实现了主调方法的资源对接口中的方法的共享, 这里主调方法是 send ,它可以想办法拿到 session,然后 它把session共享给了 createMessage()方法;
如果说一般数据类型数据做为形参,主调方法是为了获取实参的值,
那么接口作为形参时,主调方法是为了获得接口的方法, 还有一点附带效果:传入的接口中的方法可以共享主调方法的参数访问权限(就是主调方法可以用的参数,接口中的方法也可以用;)
- 第二个问题: 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是一个定时任务调度框架, 它关心的只要两件事情:
- 要做什么事情---->jobDetail(即任务详情)
- 什么时候做,频率是什么---->SimpleTrigger(依据时间)/CronTriggerFactoryBean(依据日历) 即:任务执行策略;
Ps:
- 任务调度员scheduler,这个是将 jobDetail 和 SimpleTrigger 进行组合,生成一个日程,
- 另外还有一点要说明一下,在实际生产中,我们 jobDetail(即任务详情)可能并不在Spring的管理之中, 但是, jobDetail(即任务详情) 却需要@autowired 被Spring管理的Service 或者其他bean, 这就违背了Spring规定:一个对象要想被注入对象,必须自己在Spring 管理之中,这个时候该怎么解决呢, 我们知道, Struts2与Spring整合时, action 没有被Spring管理,却可以注入被Spring管理的Service, 这里我们使用同样的方法解决这个问题,那就是创建了一个可以使 我们的 jobDetail 具有可以自动注入功能的工厂类 JobFactory ;我们在实际配置中是将 jobDetail 注入 SimpleTrigger ,再将 SimpleTrigger 注入 SchedulerFactoryBean ,那么,此时我们将 JobFactory 注入到 SchedulerFactoryBean 中,那么创建出来的 jobDetail 就具有了自动注入的功能; 问题得以解决;
- 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>
- 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());
}
}
- 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>
- 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>
- 附上 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是一个内存数据库,由于存取速度非常快,往往用作缓存; 作为一个数据库, 无非就是考虑两个问题:
- 怎么连接这个数据库,
- 怎么操作这个数据库;
- 配置连接池基本参数:
<!-- 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>
- 配置连接工厂:
<!-- 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" />
- 配置模板:
<!-- 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>
- Java代码编写示例:
// 2.将激活码保存到redis中 可以设置存货时间;
redisTemplate.opsForValue().set(model.getTelephone(), activeCode, 24, TimeUnit.HOURS);
6.持久层框架配置套路总结:
其实:持久层无非做了两件事: 1.连接数据库, 2操作数据库 ;围绕这两件事每个框架都各有千秋,但是它们与Spring整合时的配置应该是有一些套路的:
1 . Spring 的JdbcTemplate
这个类简化了JDBC操作,
它的基本操作: update(sql语句, 参数); query(sql语句, 参数);
操作流程如下:
- 配置驱动连接池 (可以用默认的,也可以单独配比如C3P0连接池),属性注入连接参数: driven, url , username , password
- 配置 JdbcTemplate
- 我们可以在java类中直接注入 JdbcTemplate 进行CRUD操作;
2.hibernate:
这是一个orm框架,通过映射文件,实现了对数据库表的操作 到 对类的对象操作的转化
操作流程如下:
- 将基本连接参数分离成一个.properties文件
- 在application.xml中引入.properties文件
- 配置连接池 (注入连接参数)
- 配置 LocalSessionFactory (注入1.连接池; 2.数据库基本配置; 3.映射文件位置 )
- 编写dao 继承 HibernateDaoSupport类 并在
- 配置dao (注入sessionFactory, 本质上是注入到HibernateDaoSupport 中) 这样在dao中就可以获得: hibernateTemplate 模板对象;
- 利用模板对象进行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在整个各种框架是,基本套路也就是:
- 配置连接参数, 2.配置连接池, 3.配置连接工厂 4.配置模板;
相比之下: SpringDataJPA做的事情更多一些,它没有直接提供给你一个模板,而是编写了一个默认实现,你只要让你的dao实现了JPARepository / JpaSpecificationExecutor , 在配上 jpa扫描:
<jpa:repositories base-package="cn.itcast.bos.dao" />
在你注入这个包下的对象时,它就会判断你是否继承了 JPARepository / JpaSpecificationExecutor 这些接口,如果继承了,那么它会利用AOP返给你一个默认实现的类,而在这个类中,已经给我们默认实现了一些CRUD常用操作,所以避免了常用CRUD操作的方法编写;