SpringMvc+Hibernate+Druid+Redis
开篇 BEGIN
实战系列作为作为个人平时练习的项目代码的记录,出这个系列主要是以下几个目的:
- 首先方便自己后续的查阅,包括像核心配置文件的获取等等
- 再者就是和大家分享,希望对您的工作有所帮助
- 最后就是能够加深理解,“理论+实践”的组合是永远不会过时的套路
这第一篇的实践给到了我们的SpringMvc+Hibernate+Druid+Redis,理论知识的获取可以从我的其他文章进行查看!
1、做什么?怎么做?
用这些东西我们要做出一个什么东西呢?我们的需求很简单:首先实现一个用户的注册和登陆,登陆后可以进行用户列表的维护。再者用户能够在首页查看公告的新闻,而为了避免频繁的访问数据库,首页的这个公告要能够缓存起来,最后就是要求对系统的行为做到一定程度的监控。
怎么做呢?我们想想,首先登陆、注册,就是用户的增、改、查,维护无非就是删除,所以一个Hibernate搞定了。公告新闻还带缓存,Redis就出场了,监控数据行为,Druid自带不用都浪费了。以上的这些都依托在SpringMvc的大的基础架构下就形成了这样一幅篇章。
好了,话不多说,一起看下吧!(下文涉及大量程序代码及其配置,概念理论主义者慎入哈!!!)
2、项目结构
项目整体结构如上图(怎么简单怎么来~),我选择的是Maven来进行整个项目依赖的整合以及Jar包的管理
3、POM.XML
添加我们需要引用的Jar包,主要就是Spring以及SpringMvc相关jar包的引入。我这边没有给出框架最精简的jar包,如果有需要,请酌情删减!
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- Maven相关通用配置 -->
<modelVersion>4.0.0</modelVersion>
<groupId>SpringTest</groupId>
<artifactId>SpringTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>SpringTest</name>
<description/>
<!-- 先定义系列jar包版本,在下面引用(推荐使用)(此处练习测试没有按照规范进行) -->
<properties>
<webVersion>3.1</webVersion>
<druid.version>1.1.10</druid.version>
<hibernate.version>4.3.11.Final</hibernate.version>
<hibernate.validator.version>5.4.1.Final</hibernate.validator.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jackson.version>1.8.4</jackson.version>
<jackson-databind.version>2.5.1</jackson-databind.version>
</properties>
<!-- 涉及jar包 -->
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.servlet.jsp.jstl</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument-tomcat</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc-portlet</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-webflow</artifactId>
<version>2.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-binding</artifactId>
<version>2.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-js</artifactId>
<version>2.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-js-resources</artifactId>
<version>2.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>opensymphony</groupId>
<artifactId>ognl</artifactId>
<version>2.6.11</version>
</dependency>
<!-- 以上是集成SpringMVC涉及Jar包,以下是自定义jar包 -->
<!-- 引入阿里的数据源连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- 导入hibernate持久层框架JAR包 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- 引入hibernate的验证框架 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate.validator.version}</version>
</dependency>
<!-- 导入spring容器整合ORM框架的相关JAR文件 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<!-- 引入spring框架与ehcache框架的兼容JAR包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<!-- 引入ehcache二级缓存相关JAR包 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.4.3</version>
</dependency>
<!-- xml操作相关 -->
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
<scope>runtime</scope>
</dependency>
<!-- dbcp连接池 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.7.0</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- redis缓存相关 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.2.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-databind.version}</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
<!-- build 相关配置 -->
<build>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<warSourceDirectory>${basedir}/WebRoot</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
4、核心配置
Web程序的配置,当然是要从web.xml开启,那么以下就是相关配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<!-- 显示名 -->
<display-name>SpringTest</display-name>
<!-- 字符过滤器 -->
<filter>
<description>字符集过滤器</description>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<description>字符集编码</description>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- druid 相关配置 BEGIN -->
<!-- web 监听配置 -->
<filter>
<filter-name>druidWebStatFilter</filter-name>
<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
<init-param>
<param-name>exclusions</param-name>
<param-value>/css/*,/context/*,/plug-in/*,*.js,*.css,*/druid*,/attached/*,*.jsp</param-value>
</init-param>
<init-param>
<param-name>principalSessionName</param-name>
<param-value>sessionInfo</param-value>
</init-param>
<init-param>
<param-name>sessionStatEnable</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>profileEnable</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>druidWebStatFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 启用自带的系统监听展示 -->
<servlet>
<servlet-name>druidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>druidStatView</servlet-name>
<url-pattern>/webpage/system/druid/*</url-pattern>
</servlet-mapping>
<!-- druid 相关配置 END -->
<!-- Spring 相关配置 BEGIN -->
<!-- Spring 上下文监听 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring 配置文件路径 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- Spring 核心调度器servlet -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- Spring 相关配置 END -->
</web-app>
然后就是SpringMvc的核心配置文件了,applicationContext.xml,如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-4.1.xsd">
<!-- spring 配置 BENGIN -->
<!-- 注解扫描配置,定义要扫描的路径,完成注入 -->
<context:component-scan base-package="com.springtest.*" />
<!-- 处理器映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!-- 处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!-- 视图解析器配置 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 定义视图前缀(路径) -->
<property name="prefix" value="/webpage/" />
<!-- 定义视图后缀(格式) -->
<property name="suffix" value=".jsp" />
</bean>
<!-- spring 配置 END -->
<!-- Hibernate 配置 BEGIN -->
<!-- 外部的数据库配置文件 -->
<context:property-placeholder location="classpath:dbconfig.properties" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!-- 自动扫描路径配置(此处简单配置全局) -->
<property name="packagesToScan">
<list>
<value>com.springtest.*</value>
</list>
</property>
<!-- hibernate相关配置 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
</props>
</property>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 配置事物管理器,通过@Transactional就可以启用事物管理 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 配置hibernate模板操作类 -->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- Hibernate 配置 END -->
<!-- DRUID 配置 BEGIN -->
<!-- 连接池配置 ,destroy-method="close" :代表spring容器在销毁时,调用close(),关闭掉所有的数据库连接对象-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 配置连接数据库最基本的3元素 (驱动可忽略) -->
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!-- 最大连接数 -->
<property name="maxActive" value="20" />
<!-- 初始化数量 -->
<property name="initialSize" value="1" />
<!-- 创建连接的超时时间,单位:毫秒 -->
<property name="maxWait" value="60000" />
<!-- 最小连接数 -->
<property name="minIdle" value="1" />
<!-- 配置校验语句 -->
<property name="validationQuery" value="${validationQuery.sql}" />
<!-- 配置校验(连接空闲时,借出时,归还时) -->
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<!-- 配置是否允许PreparedStatements对象的缓存 -->
<property name="poolPreparedStatements" value="true" />
<property name="maxOpenPreparedStatements" value="20" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<!-- 配置连接池中,创建连接时,采用异步|同步方式来进行创建,默认是:异步 -->
<property name="asyncInit" value="true" />
<!-- 配置额外的扩展插件:stat 代表开启监控程序,wall 代表开启防SQL注入功能 -->
<property name="filters" value="wall,stat" />
<!-- 打开removeAbandoned功能 -->
<property name="removeAbandoned" value="true" />
<!-- 1800秒,也就是30分钟 -->
<property name="removeAbandonedTimeout" value="3600" />
<!-- 关闭abanded连接时输出错误日志 -->
<property name="logAbandoned" value="true" />
<!-- 如果有定制化的过滤器,可以使用proxyFilters 去做一个引用 -->
<property name="proxyFilters">
<list>
<ref bean="stat-filter" />
<ref bean="log-filter" />
</list>
</property>
<!-- Oracle连接是获取字段注释 -->
<property name="connectProperties">
<props>
<prop key="remarksReporting">true</prop>
</props>
</property>
</bean>
<!-- 定制化的监控过滤器 -->
<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter">
<property name="slowSqlMillis" value="200" />
<property name="logSlowSql" value="true" />
</bean>
<!-- 定制化的日志过滤器 -->
<bean id="log-filter" class="com.alibaba.druid.filter.logging.Log4jFilter">
<!-- 开启数据源相关的日志记录 -->
<property name="dataSourceLogEnabled" value="true" />
<!-- 连接错误时,记录相关日志 -->
<property name="connectionLogErrorEnabled" value="true"></property>
<!-- 预编译对象,发生错误时记录相关日志 -->
<property name="statementLogErrorEnabled" value="true"></property>
</bean>
<!-- druid支持spring监控 -->
<bean id="druid-stat-interceptor"
class="com.alibaba.druid.support.spring.stat.DruidStatInterceptor">
</bean>
<bean id="druid-stat-pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"
scope="prototype">
<property name="patterns">
<list>
<value>com.springtest.*</value>
</list>
</property>
</bean>
<aop:config>
<aop:advisor advice-ref="druid-stat-interceptor" pointcut-ref="druid-stat-pointcut" />
</aop:config>
<!-- DRUID 配置 END -->
<!-- JDBC配置 BEGIN-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<!-- JDBC配置 END-->
<!-- 缓存配置 BEGIN-->
<!-- Hibernate缓存配置 -->
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cache-manager-ref="ehcache" />
<!-- spring缓存配置 -->
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:config-location="classpath:ehcache.xml" />
<!-- 导入Redis缓存配置 -->
<import resource="classpath:springtest-redis.xml" />
<!-- 缓存配置 END-->
<!-- 其他配置 BEGIN-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 其他配置 END-->
</beans>
因为我们还用到了Redis,所以必不可少要对其做相应的配置,如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:redis="http://www.springframework.org/schema/redis"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-3.1.xsd
http://www.springframework.org/schema/redis
http://www.springframework.org/schema/redis/spring-redis-1.0.xsd">
<!-- jedis 配置 BEGIN-->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最大空闲连接数 -->
<property name="maxIdle" value="300" />
<!-- 最小空闲连接数 -->
<property name="minIdle" value="1" />
<property name="maxWaitMillis" value="1000" />
<!-- 在获取连接的时候检查有效性 -->
<property name="testOnBorrow" value="false" />
</bean>
<!-- jedis 配置 END-->
<!-- redis服务器中心 BEGIN-->
<bean id="redisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="poolConfig" ref="poolConfig" />
<property name="port" value="6379" />
<property name="hostName" value="127.0.0.1" />
<property name="timeout" value="10000" />
<property name="database" value="0" />
</bean>
<!-- redis服务器中心 END-->
<!-- redis模板 BEGIN-->
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="redisConnectionFactory" />
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="redisConnectionFactory"/>
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
</property>
</bean>
<!-- redis模板 END-->
</beans>
好了,配置大功告成,接下来看看其他的组件吧
5、业务控制器
这边给出首页的控制器,这里面包含有Hibernate、Jedis(Java 操作Redis组件)的应用,如下:
/***
* index 控制器
* @author hjf
* @version 练习版本,无任何优化处理,仅供参考
* @date 2018-05-10
*/
@Controller
@RequestMapping("/index")
public class IndexController {
/**
* 初始化Log4j的一个实例
*/
private static final Logger logger = Logger.getLogger(IndexController.class);
@Autowired
private ICommonDBService commonDBService;
@Autowired
private IRedisService redisService;
// 新闻缓存的Key值
private static final String NEWS_REDIS_KEY = "NEWS_REDIS_KEY";
/**
* 登陆页面
* @return
*/
@RequestMapping(params = "login")
public ModelAndView login() {
return new ModelAndView("login");
}
/***
* 注册页面
* @return
*/
@RequestMapping(params = "register")
public ModelAndView register() {
return new ModelAndView("register");
}
/**
* 验证登陆
* 1、验证用户名密码是否正确
* 2、封装首页信息并返回
* @param username 用户名
* @param userpwd 密码
* @return
*/
@RequestMapping(params = "doLogin")
public String doLogin(String username,String userpwd,HttpServletRequest request){
try {
if(StringUtils.isEmpty(username) || StringUtils.isEmpty(userpwd)){
return "login_fail";
}
//1、 进行用户身份认证
User user = commonDBService.findHqlOne(User.class, " from User where username = ? ", username);
if(user == null){
return "login_fail";
}
if(StringUtils.isNotBlank(user.getPassword()) && user.getPassword().equals(userpwd)){
//2、用户信息认证成功,封装首页数据
//2.1、 查找用户列表
List<User> memberList = commonDBService.findHql(" from User where username != ?",username);
if(memberList == null){
memberList = new ArrayList<User>();
}
request.setAttribute("memberList", memberList);
//2.2、获取热点新闻列表,首先通过Redis获取,如果能获取到直接返回
//如果获取不到则去数据库获取并更新热点新闻
List<Object> tList = redisService.getList(NEWS_REDIS_KEY); //将列表设置到缓存
List<News> list = new ArrayList<News>();
if(tList != null && tList.size() > 0){
//直接从Redis缓存取数据
for (Object item : tList) {
list.add((News) item);
}
System.out.println("从缓存获取首页数据");
} else {
//缓存中无数据,从数据库中进行获取
list = commonDBService.findAll(News.class);
if(list != null){
//将取出的数据缓存到Redis并设置过期时间
redisService.setList(NEWS_REDIS_KEY, list, 6000);
System.out.println("从数据库获取首页数据");
}
}
request.setAttribute("newsList", list);
return "index";
}
return "login_fail";
} catch (Exception e) {
logger.error(e);
}
return "login_fail";
}
/**
* 执行注册
* @param username 用户名
* @param userpwd 密码
* @return
*/
@RequestMapping(params = "doRegister")
public String doRegister(String username,String userpwd){
if(StringUtils.isEmpty(username) || StringUtils.isEmpty(userpwd)){
return "register_fail";
}
User user = new User();
user.setId(username);
user.setUsername(username);
user.setPassword(userpwd);
commonDBService.save(user);
return "login";
}
@RequestMapping(params = "doDelete")
public String doDelete(String username){
if(StringUtils.isEmpty(username) ){
return "login_fail";
}
User user = commonDBService.findOneByProperty(User.class, "username", username);
if(user == null){
return "login_fail";
}
commonDBService.delete(user);
return "index";
}
}
6、关键服务类
贴出DB的关键服务类,主要用来集成Hibernate和Jdbc来操作数据库
@Service("commonDBService")
@Transactional
public class CommonDBServiceImpl implements ICommonDBService {
@Autowired
public ICommonDBDao commonDao = null;
@Resource
public void setCommonDao(ICommonDBDao commonDao) {
this.commonDao = commonDao;
}
/********************Hibernate模块************************************/
/**
* 获取session
* 2018-05-17
* @author hjf
* @return 返回session对象
*/
public Session getSession() {
return commonDao.getSession();
}
/**
* 保存对象
* 2018-05-17
* @author hjf
* @param entity 要保存的实体
* @return 保存后的实体Id
*/
public <T> Serializable save(T entity) {
return commonDao.save(entity);
}
/**
* 批量保存
* 2018-05-17
* @author hjf
* @param entityList 要保存的实体列表
* @return
*/
public <T> void batchSave(List<T> entitys) {
this.commonDao.batchSave(entitys);
}
/**
* 保存或更新实体
* 2018-05-17
* @author hjf
* @param entity 要保存的实体对象
* @return
*/
public <T> void saveOrUpdate(T entity) {
commonDao.saveOrUpdate(entity);
}
/**
* 删除实体
* 2018-05-17
* @author hjf
* @param entity 要删除的实体
* @return
*/
public <T> void delete(T entity) {
commonDao.delete(entity);
}
/**
* 通过主键Key获取实体
* 2018-05-17
* @author hjf
* @param clazz 要获取实体类型
* @param id 主键Key
* @return 实体对象
*/
public <T> T get(Class<T> clazz, Serializable id) {
return commonDao.get(clazz, id);
}
/**
* 通过主键Key获取实体
* 2018-05-17
* @author hjf
* @param clazz 要获取实体类型
* @param id 主键Key
* @return 实体对象
*/
public <T> T getEntity(Class<T> clazz, Serializable id){
return commonDao.get(clazz, id);
}
/**
* 离线获取列表
* 2018-05-17
* @author hjf
* @param dc 查询载体
* @return 实体列表
*/
public <T> List<T> findByDetached(DetachedCriteria dc) {
return this.commonDao.findByDetached(dc);
}
/**
* Hql查找实体列表
* 2018-05-17
* @author hjf
* @param hql hql语句
* @param 参数列表
* @return 实体列表
*/
public <T> List<T> findHql(String hql, Object... param) {
return this.commonDao.findHql(hql, param);
}
/**
* Hql查找单一实体
* 2018-05-17
* @author hjf
* @param clazz 实体类型
* @param hql 查询语句
* @param param 参数列表
* @return 实体对象
*/
public <T> T findHqlOne(Class<T> clazz,String hql, Object... param) {
return this.commonDao.findHqlOne(clazz, hql, param);
}
/**
* Hql返回指定条数的实体
* 2018-05-17
* @author hjf
* @param hql 查询语句
* @param size 返回的条数
* @param param 参数列表
* @return
*/
public <T> List<T> findLimitHql(String hql,int size, Object... param) {
return this.commonDao.findLimitHql(hql,size, param);
}
/**
* 通过属性返回唯一实体
* 2018-05-17
* @author hjf
* @param clazz 实体类型
* @param propertyName 属性名册合格
* @param value 属性值
* @return 实体对象
*/
public <T> T findOneByProperty(Class<T> clazz, String propertyName, Object value) {
return commonDao.findUniqueByProperty(clazz, propertyName, value);
}
/**
* 通过属性获取实体列表
* 2018-05-17
* @author hjf
* @param clazz 实体类型
* @param propertyName 属性名称
* @param value 属性值
* @return 实体列表
*/
public <T> List<T> findByProperty(Class<T> clazz, String propertyName, Object value) {
return commonDao.findByProperty(clazz, propertyName, value);
}
/**
* 通过主键删除实体
* 2018-05-17
* @author hjf
* @param clazz 实体类型
* @param id 主键Key
* @return
*/
public <T> void deleteEntity(Class<T> clazz, Serializable id) {
commonDao.deleteEntity(clazz, id);
}
/**
* 删除实体集合
* 2018-05-17
* @author hjf
* @param entityList 实体集合
* @return
*/
public <T> void deleteEntities(Collection<T> entityList) {
commonDao.deleteEntities(entityList);
}
/**
* 更新实体对象
* 2018-05-17
* @author hjf
* @param entity 要更新的实体
* @return
*/
public <T> void updateEntity(T entity) {
commonDao.updateEntity(entity);
}
/**
* 查找全部实体
* 2018-05-17
* @author hjf
* @param clazz 要查找的实体类
* @return 全部实体列表
*/
public <T> List<T> findAll(final Class<T> clazz) {
return commonDao.findAll(clazz);
}
/**
* Hql通过SQL语句获取实体列表
* 2018-05-17
* @author hjf
* @param sql 查询语句
* @return 实体列表
*/
public <T> List<T> findListbySql(String sql) {
return commonDao.findListbySql(sql);
}
/********************jdbc模块************************************/
/**
* jdbc 查找实体列表
* 2018-05-17
* @author hjf
* @param sql 查询语句
* @param clazz 实体类型
* @param param 参数
* @return 实体列表
*/
public <T> List<T> findListByJdbc(String sql,Class<T> clazz, Object... param) {
return commonDao.findListByJdbc(sql, clazz, param);
}
/**
* jdbc 查找单一实体
* 2018-05-17
* @author hjf
* @param sql 查询语句
* @param clazz 返回的实体类型
* @param param 参数列表
* @return 实体对象
*/
public <T> T findOneByJdbc(String sql,Class<T> clazz, Object... param) {
return commonDao.findOneByJdbc(sql, clazz, param);
}
/**
* 执行SQL语句
* 2018-05-17
* @author hjf
* @param sql 执行语句
* @param param 参数列表
* @return 受影响行数
*/
public Integer executeSqlByJdbc(String sql, List<Object> param) {
return commonDao.executeSqlByJdbc(sql, param);
}
/**
* jdbc jdbc 执行SQL
* 2018-05-17
* @author hjf
* @param sql 执行语句
* @param param 参数列表
* @return 受影响行数
*/
public Integer executeSqlByJdbc(String sql, Object... param) {
return commonDao.executeSqlByJdbc(sql, param);
}
/**
* jdbc 执行存储过程
* 2018-05-17
* @author hjf
* @param procedureSql 执行语句
* @param param 参数列表
* @return 实体列表
*/
public <T> List<T> executeProcedure(String procedureSql,Object... param) {
return this.commonDao.executeProcedure(procedureSql, param);
}
}
7、Redis 的使用
这里面我们为了更好的加快数据的读取,对于像后台管理公共此类的数据进行了缓存处理,定期的更新这个缓存。而缓存选取的是Redis,这边不做简要的介绍,后面的文章再做系统的介绍。
以下是缓存操作的服务实现类RedisServiceImpl源码如下:
/***
* redis 缓存操作接口
* @author hjf
* @version v-test 测试版本,仅供自己练习使用,未做任何优化封装处理
* 2018-05-19
*/
@Service("redisServiceImpl")
public class RedisServiceImpl implements IRedisService {
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private RedisTemplate<String,Object> redisTemplate;
/**
* 删除key和value
*/
public void delete(String key){
stringRedisTemplate.delete(key);
}
/**
* 根据key获取value
*/
public String get(String key){
String value = stringRedisTemplate.opsForValue().get(key);
return value;
}
/**
* 将key和value存入redis,并设置有效时间,单位:天
*/
public void set(String key, String value, long timeout){
stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.DAYS);
}
/**
* 将key和value存入redis
*/
public void set(String key, String value){
stringRedisTemplate.opsForValue().set(key, value);
}
/**
* 从redis中获取map
*/
public Map<String, Object> getMap(String key){
HashOperations<String, String, Object> hash = stringRedisTemplate.opsForHash();
Map<String,Object> map = hash.entries(key);
return map;
}
/**
* 将map存入redis,并设置时效
*/
public void set(String key, Map<? extends String, ? extends Object> map, long timeout){
stringRedisTemplate.opsForHash().putAll(key, map);
stringRedisTemplate.expire(key, timeout, TimeUnit.DAYS);
}
/**
*
* 此方法将ArrayList集合直接存储为一个字符串
* @param key
* 存储的名字
* @param list
* 要存储的集合对象
* @param activeTime
* 该对象的有效时间,单位为秒
*/
public <T> boolean setList(String key, List<T> list,Integer activeTime) {
if (list != null && key != null && key != "") {
//首先移除原先缓存
redisTemplate.delete(key);
for (T item : list) {
redisTemplate.opsForList().leftPush(key, item);
}
return true;
}
return false;
}
/**
* 此方法将会把存在redis中的数据取出来,并封装成相应的Arraylist集合
* @param key
* Key值
* @return List
*/
public List<Object> getList(String key) {
if (key != null && key != "" ) {
List<Object> list = redisTemplate.opsForList().range(key, 0, -1); //获取缓存中所有的元素
return list;
}
return null;
}
}
8、Druid 监控配置
Druid 作为一款非常优秀的开源连接池组件(阿里出品,必属~~),它给我们提供了不只是对于连接池的特性,还能够帮助我们进行系统核心内容的监控,一举两得,何乐而不为呢。下面我们简要了解下吧:
- 连接池。提供并帮助我们进行主流数据库的连接池管理
- 数据源信息的读取和监控。
- SQL情况执行监控。帮助我们分析数据库的访问性能,让我们更好的进行SQL的优化,而且还能进行防注入配置
- 数据库加密。公私钥的配置方式方便我们加密我们的数据库访问信息
- SQL执行日志。内置多种LogFilter可以帮助我们进行日志的处理
- 灵活、开源、可扩展性强!(这个就不用多说了~)
在上面的配置文件中我已经配置了启用内置的监控,那么要怎么使用呢?
很简单,只要访问他的默认路径即可,路径为:/system/druid/index,直接访问就可以看到如以下的默认界面
9、结果展示
好了,让我们来看下最终首页呈现的效果吧
10、THE END
好了整个Demo的核心就是这些了,如果有小伙伴对于一些理论知识还不是很了解的话,可以关注我的其他文章,有主要内容的详细介绍。
如果有写的不好的或者是有问题的地方还希望您能与我联系,关注网站http://missxhh.com,获得更多有关于我的信息吧!
谢谢阅读,您的关注就是对我最大的动力!!!