实战(一):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 作为一款非常优秀的开源连接池组件(阿里出品,必属~~),它给我们提供了不只是对于连接池的特性,还能够帮助我们进行系统核心内容的监控,一举两得,何乐而不为呢。下面我们简要了解下吧:

  1. 连接池。提供并帮助我们进行主流数据库的连接池管理
  2. 数据源信息的读取和监控
  3. SQL情况执行监控。帮助我们分析数据库的访问性能,让我们更好的进行SQL的优化,而且还能进行防注入配置
  4. 数据库加密。公私钥的配置方式方便我们加密我们的数据库访问信息
  5. SQL执行日志。内置多种LogFilter可以帮助我们进行日志的处理
  6. 灵活、开源、可扩展性强!(这个就不用多说了~)

在上面的配置文件中我已经配置了启用内置的监控,那么要怎么使用呢?
很简单,只要访问他的默认路径即可,路径为:/system/druid/index,直接访问就可以看到如以下的默认界面
在这里插入图片描述

9、结果展示

好了,让我们来看下最终首页呈现的效果吧
在这里插入图片描述

10、THE END

好了整个Demo的核心就是这些了,如果有小伙伴对于一些理论知识还不是很了解的话,可以关注我的其他文章,有主要内容的详细介绍。

如果有写的不好的或者是有问题的地方还希望您能与我联系,关注网站http://missxhh.com,获得更多有关于我的信息吧!

谢谢阅读,您的关注就是对我最大的动力!!!

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