實戰(一):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,獲得更多有關於我的信息吧!

謝謝閱讀,您的關注就是對我最大的動力!!!

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