使用Intellij Idea+Gradle 搭建Java 本地開發環境
Java 本地開發環境搭建
項目搭建采用技術棧為:Spring+Spring MVC+Hibernate+Jsp+Gradle+tomcat+mysql5.6
搭建環境文檔目錄結構說明:
- 使用Intellj Idea 搭建項目過程詳解
- 項目各配置文件講解及部署
- 各層包功能講解&項目搭建完畢最終效果演示圖
- 項目中重要代碼講解
5.配置tomcat 運行環境
6.webapp文件夾下分層詳解
1. 使用Intellj Idea 搭建項目過程詳解
1.1 打開Intellj Idea
1.2 操作 Intellj Idea 工具欄 新建項目
需要說明的是,最初創建的項目視圖是不完整的,包括webapp文件夾下沒有web.xml,以及src包下缺少Java文件夾(放置java源代碼文件),Resources文件夾(放置項目配置文件)。
我們繼續做以下操作,使得項目的結構符合web 應用項目的層級標準。
出現如下視圖:
接下來:單擊main文件夾按照如下操作:
屏幕快照 2016-11-20 下午4.44.33.png
點擊ok,再按照上圖操作操作一遍,輸入文件名為 resources
最終的結構圖如下圖所示:
2. 項目各配置文件講解及部署
完成了項目的初始化結構創建,接下來我們需要來創建配置文件。
首先是resources文件夾下的配置文件
2.1resources下資源文件截圖:(最終配置的結果)
2.2 data-access-applicationContext.xml
主要管理數據庫訪問組件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="
<!-- 配置自動掃描的包 -->
<context:component-scan base-package="com.fxmms" use-default-filters="false">
<context:include-filter type="regex" expression="com.fxmms.*.*.dao.*"/>
<context:include-filter type="regex" expression="com.fxmms.*.dao.*"/>
</context:component-scan>
<!-- 配置數據源 -->
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.jdbcUrl}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--配置hibernate SessionFactory-->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${dataSource.hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${dataSource.hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">true</prop>
<!--負責自動創建數據表,基本上不能打開注釋,否則所有的數據庫中表信息都會被刪除,重新創建-->
<!-- <prop key="hibernate.hbm2ddl.auto">create</prop> -->
</props>
</property>
<!-- <property name="hibernate.jdbc.batch_size" value="50"></property> -->
<property name="packagesToScan">
<list>
<value>com.fxmms.*.*.domain</value>
<value>com.fxmms.*.domain</value>
</list>
</property>
</bean>
<!--jdbcTemplate start -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--Spring JDBC 中操作 LOB 數據 -->
<bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"
lazy-init="true"></bean>
<!-- 配置JPA部分 -->
<!-- 配置JPA的EntityManagerFactory -->
<!-- <bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
</property>
<property name="packagesToScan" value="com.fxmms"></property>
<property name="jpaProperties">
<props>
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory
</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
</props>
</property>
<!–使用二級緩存–>
<property name="sharedCacheMode" value="ENABLE_SELECTIVE"></property>
</bean>
<!– 配置事務 –>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>-->
<!-- <!– 配置SpringData部分 –>
<jpa:repositories base-package="com.fxmms"
entity-manager-factory-ref="entityManagerFactory">
</jpa:repositories>-->
</beans></code></pre>
2.3 service-applicationContext.xml
主要管理業務邏輯組件,包括對數據庫訪問的事務控制,以及定時任務。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/task
;
<aop:aspectj-autoproxy/>
<!--設置定時任務-->
<task:annotation-driven/>
<context:component-scan base-package="com.fxmms.www" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</beans></code></pre>
2.4default-servlet.xml
設置springmvc-applicationContext.xml,前端控制器將請求轉發到相應的controller層中的處理方法上。
<?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"
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.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!---->
<mvc:annotation-driven>
<!--json解析-->
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
<context:component-scan base-package="com.fxmms.www.controller">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--因為web.xml中defaultDispatcherServlet對所有請求進行了攔截,所以對一些.css .jpg .html .jsp也進行了攔截,所以此配置項
保證對對靜態資源不攔截-->
<mvc:default-servlet-handler/>
<!--視圖解析器-->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--配置文件上上傳-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"/>
<property name="maxUploadSize" value="10485760000"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
</beans>
2.5 spring-security.xml
設置spring-security 權限控制配置文件,項目中權限的控制統一在此配置文件中配置,包括從數據庫中獲取用戶的相關信息,以及配置相應pattern的請求過濾規則。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security
;
<!-- <sec:http pattern="//*.jpg" security="none"></sec:http>
<sec:http pattern="//.jpeg" security="none"></sec:http>
<sec:http pattern="/**/.gif" security="none"></sec:http>
<sec:http pattern="//*.png" security="none"></sec:http>s
<sec:http pattern="/getCode" security="none" /><!– 不過濾驗證碼 –>
<sec:http pattern="/test/" security="none"></sec:http><!– 不過濾測試內容 –>-->
<!--spring security 權限管理配置文件-->
<context:component-scan base-package="com.fxmms.common.security">
</context:component-scan>
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!--權限控制-->
<sec:http auto-config="true" use-expressions="true">
<sec:intercept-url pattern="/superadmin/" access="hasRole('superadmin')"/>
<sec:intercept-url pattern="/admin/" access="hasRole('admin')"/>
<sec:intercept-url pattern="/customer/**" access="hasRole('customer')"/>
<!--自定義登陸頁面,權限驗證失敗頁面,登錄成功頁面-->
<sec:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp" login-processing-url="/j_spring_security_check"
authentication-success-handler-ref="loginSuccessHandler"/>
<!--用戶權限不一致出現的權限不可得情況,默認情況下跳轉到403頁面-->
<sec:access-denied-handler ref="accessDeniedServletHandler" />
<sec:logout logout-success-url="/login.jsp" />
</sec:http>
<sec:authentication-manager>
<sec:authentication-provider>
<!--配置從數據庫查詢用戶權限 and isDelete = 0 and enable = 1-->
<sec:jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select userName,password,enable from mms_admin where userName=? and isDelete = 0 and enable = 1"
authorities-by-username-query="select userName,role from mms_admin where username=?"
></sec:jdbc-user-service>
</sec:authentication-provider>
</sec:authentication-manager>
</beans></code></pre>
2.6 db.properties
數據庫訪問配置文件
jdbc.user=root
jdbc.password=feixun*123
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost/fxmms?useUnicode=true&characterEncoding=UTF-8
jdbc.jdbcUrl=jdbc:mysql://222.73.156.132:13306/fxmms?useUnicode=true&characterEncoding=UTF-8
jdbc.initPoolSize=5
jdbc.maxPoolSize=20
dataSource.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
#
local
#
dataSource.hibernate.show_sql=true</code></pre>
2.7 log4j.properties
配置項目日志文件,日志輸出模式為Console
###########################################################################
Properties file for the log4j logger system
#
Note: During the uPortal build, the file at /properties/Logger.properties is copied
to the log4j standard location /WEB-INF/classes/log4j.properties . This means that editing the file
at /properties/Logger.properties in a deployed uPortal will have no effect.
#
Please read the instructions for the Log4J logging system at
http://jakarta.apache.org/log4j/ if you want to modify this.
#
You should probably replace the word "debug" with "info" in the
following line after everything is running. This will turn off
the tons of debug messages, and leave only INFO, WARN, ERROR, etc.
#
log4j.rootLogger=info, stdout
Console output
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{mm:ss,SSS} %p [%l] - <%m>%n</code></pre>
2.8 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--配置權限過濾器,注意必須配置在springmvc 之前,因為對用戶訪問資源的權限判斷與控制是在訪問特定url之前發生的-->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置字符編碼過濾器 必須配置在所有過濾器的最前面 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--超級管理員 -->
<!-- <filter>
<filter-name>superAdminFilter</filter-name>
<filter-class>com.fxmms.filter.SuperAdminFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>superAdminFilter</filter-name>
<url-pattern>/fxmms/superadmin/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>adminFilter</filter-name>
<filter-class>com.fxmms.filter.AdminFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>adminFilter</filter-name>
<url-pattern>/fxmms/admin/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>customerFilter</filter-name>
<filter-class>com.fxmms.filter.CustomerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>customerFilter</filter-name>
<url-pattern>/fxmms/customer/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.fxmms.servlet.LoginServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>InvalidateServlet</servlet-name>
<servlet-class>com.fxmms.servlet.InvalidateServlet</servlet-class>
</servlet>-
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/loginServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>InvalidateServlet</servlet-name>
<url-pattern>/invalidateServlet</url-pattern>
</servlet-mapping>-->
<!-- 配置看可以把POST請求轉為PUT,DELETE請求的Filter -->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--配置中央控制器,對所有請求進行攔截并做請求路徑,與處理請求樁模塊之間的映射-->
<servlet>
<servlet-name>defaultDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation
</param-name>
<param-value>classpath:default-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!--這里是攔截所有-->
<servlet-mapping>
<servlet-name>defaultDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app></code></pre>
2.9 build.gradle
項目構建腳本
group 'com.fxmms'
version '1.0-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'war'
sourceCompatibility = 1.8
repositories {
maven { url "
maven { url '
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
// servlet-api
compile group: 'javax.servlet', name: 'servlet-api', version: '2.5'
//spring相關
compile group: 'org.springframework', name: 'spring-webmvc', version: '4.3.3.RELEASE'
compile group: 'org.springframework', name: 'spring-orm', version: '4.3.3.RELEASE'
compile group: 'org.springframework', name: 'spring-aspects', version: '4.3.3.RELEASE'
compile group: 'org.springframework.security', name: 'spring-security-config', version: '3.2.0.RELEASE'
compile group: 'org.springframework.security', name: 'spring-security-taglibs', version: '3.2.0.RELEASE'
compile 'org.springframework.security:spring-security-web:3.2.0.RELEASE'
//hibernate相關
compile 'org.hibernate:hibernate-core:4.3.6.Final'
//c3p0連接池
compile group: 'org.hibernate', name: 'hibernate-c3p0', version: '4.3.6.Final'
//ehcahe二級緩存
compile group: 'org.hibernate', name: 'hibernate-ehcache', version: '4.3.6.Final'
//mysql
compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.39'
//springData
compile group: 'org.springframework.data', name: 'spring-data-jpa', version: '1.10.3.RELEASE'
// https://mvnrepository.com/artifact/log4j/log4j日志
compile group: 'log4j', name: 'log4j', version: '1.2.17'
//json解析相關
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.5.4'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.5.4'
//迅雷接口有關jar 包
compile 'org.apache.httpcomponents:httpclient:4.4'
compile 'org.json:json:20141113'
compile group: 'org.apache.clerezza.ext', name: 'org.json.simple', version: '0.4'
//https://mvnrepository.com/artifact/org.apache.commons/commons-io 讀取文件相關
compile group: 'org.apache.commons', name: 'commons-io', version: '1.3.2'
// https://mvnrepository.com/artifact/org.apache.poi/poi 文件讀取相關 apache-poi
compile group: 'org.apache.poi', name: 'poi', version: '3.9'
// https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml 解決execl 版本差異
compile group: 'org.apache.poi', name: 'poi-ooxml', version: '3.9'
// https://mvnrepository.com/artifact/commons-io/commons-io 文件上傳
compile group: 'commons-io', name: 'commons-io', version: '1.3.1'
// https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
compile group: 'commons-fileupload', name: 'commons-fileupload', version: '1.2.2'
}</code></pre>
3. 各層包功能講解&項目搭建完畢最終效果演示圖
3.1 項目中各層包功能講解
項目中Java源代碼層級結構如下圖所示:

對于www包中的各分層,我們對照上圖重點說明:
controller:用于路由各種http訪問,其中可以實現對前臺頁面參數的對象化綁定,這個功能的實現是依賴于spring mvc中的參數綁定功能,以及返回向前端頁面返回數據。也可以實現基于Restful 風格API的編寫。
dao:用于實現對數據庫的操作,包中的代碼繼承并實現自common中的dao 層代碼,采用的是類的適配器模式實現的,這里的代碼值得細細品味,可以說是整個項目的靈魂所在之處。
domain:項目的實體類都存在于這個包中,其中的類與數據庫表相對應。
dto:實現了序列化的數據傳輸層對象,用于接收前臺參數,并封裝成dto 對象傳輸至后臺,也負責從數據庫中查詢數據的封裝。
qo:模糊查詢對象所在的包,用于封裝QBC動態查詢參數。
rowmapper:用于對應jdbcTemplate查詢數據庫返回對象的數據集,并將數據集依照此對象進行封裝。
schedulejob:定時任務類所在的包,其中類要加上@Service注解,因為定時任務注解配置在service-applicationContext.xml中,包掃描組件的規則是只掃描有@Service注解的組件類
service:業務邏輯層,主要完成業務邏輯的書寫,其中調用了dao實現類中的方法,并且每個有關于數據庫操作的方法上都加上了@Transaction注解,@Transaction是Spring Framework對AOP 的另一種區別于攔截器的自定義注解實現。
4.項目中重要代碼講解
主要講解一下Dao層中代碼對適配器設計模式的應用:
4.1 首先看下commom層中 BaseDao.java
package com.fxmms.common.dao;
import com.fxmms.common.ro.Dto;
import com.fxmms.common.ro.DtoResultWithPageInfo;
import com.fxmms.common.ro.PageQo;
import org.hibernate.Criteria;
import org.springframework.stereotype.Repository;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/*
- @param <T>
@usage 數據庫公共操作接口
*/
@Repository
public interface BaseDao<T> {
/*
- @param id
- @usage 根據id獲取數據庫中唯一紀錄,封裝成java對象并返回
- @return T
*/
public T getById(Serializable id);
/**
- @param id
- @usage 根據id懶加載數據庫中唯一紀錄,封裝成java對象并返回
- @return T
*/
public T load(Serializable id);
/**
- @param columnName
- @param value
*
- @usage 根據列名,以及對應的值獲取數據庫中惟一紀錄,封裝成Java對象并返回
- @return
*/
public T getByUniqueKey(String columnName, Object value);
/**
- @param nameValuePairs
- @return T
*/
public T getUniqueResult(Map<String, Object> nameValuePairs);
/**
- @param columnName
- @param value
- @param sort
- @param order
- asc/desc
- @return List<T>
*/
public List<T> getListByColumn(String columnName, Object value,
String sort, String order);
public List<T> getListByColumn(String columnName, Object value);
/**
- ?
- @param nameValuePairs
- @param sort
- @param order
- asc/desc
- @return List<T>
*/
public List<T> getListByColumns(Map<String, Object> nameValuePairs,
String sort, String order);
public List<T> getListByColumns(Map<String, Object> nameValuePairs);
/**
- @return List<T>
*/
public List<T> getAll();
/**
- @param t
- @return Serializable id
*/
public Serializable save(T t);
/**
- @param t
*/
public void update(T t);
/**
- @param t
*/
public void delete(T t);
/**
- QBC
- @return
*/
public Criteria createCriteria();
/**
- @param <E>
- @param <D>
- @param criteria
- @param pageNo
- @param pageSize
- @param dtoClazz
- @return
*/
public <E, D extends Dto> DtoResultWithPageInfo<D> queryPageListByCriteria(
Criteria criteria, int pageNo, int pageSize, Class<D> dtoClazz);
/**
- @param <E>
- @param <D>
- @param criteria
- @param qo
- @param class1
- @return
*/
public <E, D extends Dto> DtoResultWithPageInfo<D> queryPageListByCriteriaWithQo(PageQo qo, Class<D> dtoClazz);
}</code></pre>
其中定義了一些對數據庫的抽象公共操作方法,代碼中有注釋,可以對照理解。
4.2 看下HibernateTemplateDao.java對BaseDao.java的抽象實現
package com.fxmms.common.dao.hib;
import com.fxmms.common.dao.BaseDao;
import com.fxmms.common.ro.Dto;
import com.fxmms.common.ro.DtoResultWithPageInfo;
import com.fxmms.common.ro.PageInfo;
import com.fxmms.common.ro.PageQo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/*
- @param <T>
- @usage 應用數據訪問的靈魂,抽象出各種模型類進行數據庫訪問的公共操作。
- 主要使用到QBC動態查詢。主要思想是利用反射。
*/
@Repository
public abstract class HibernateTemplateDao<T> implements BaseDao<T> {
protected static final Log log = LogFactory
.getLog(HibernateTemplateDao.class);
//通過反射,可以實現對不同類對應的數據表的操作
protected abstract Class<?> getEntityClass();
protected SessionFactory sessionFactory;
@Autowired
@Qualifier("sessionFactory")
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Session getSession() {
return sessionFactory.getCurrentSession();
}
public Session openNewSession() {
return sessionFactory.openSession();
}
@Override
@SuppressWarnings("unchecked")
public T getById(Serializable id) {
return (T) getSession().get(getEntityClass(), id);
}
@Override
@SuppressWarnings("unchecked")
public T getByUniqueKey(String columnName, Object value) {
return (T) getSession().createCriteria(getEntityClass())
.add(Restrictions.eq(columnName, value)).uniqueResult();
}
@Override
@SuppressWarnings("unchecked")
public List<T> getListByColumn(String columnName, Object value,String sort,String order) {
Criteria criteria = getSession().createCriteria(getEntityClass());
criteria.add(Restrictions.eq(columnName, value));
if(StringUtils.hasText(sort) && StringUtils.hasText(order)){
if("asc".equals(order)){
criteria.addOrder(Order.asc(sort));
}else if("desc".equals(order)){
criteria.addOrder(Order.desc(sort));
}
}
List<T> list = criteria.list();
return list;
}
@Override
@SuppressWarnings("unchecked")
public List<T> getListByColumn(String columnName, Object value) {
Criteria criteria = getSession().createCriteria(getEntityClass());
criteria.add(Restrictions.eq(columnName, value));
List<T> list = criteria.list();
return list;
}
@Override
@SuppressWarnings("unchecked")
public List<T> getListByColumns(Map<String, Object> nameValuePairs,String sort,String order){
Criteria criteria = getSession().createCriteria(getEntityClass());
for (Map.Entry<String, Object> entry : nameValuePairs.entrySet()) {
criteria.add(Restrictions.eq(entry.getKey(), entry.getValue()));
}
if(StringUtils.hasText(sort) && StringUtils.hasText(order)){
if("asc".equals(order)){
criteria.addOrder(Order.asc(sort));
}else if("desc".equals(order)){
criteria.addOrder(Order.desc(sort));
}
}
List<T> list = criteria.list();
return list;
}
@Override
@SuppressWarnings("unchecked")
public List<T> getListByColumns(Map<String, Object> nameValuePairs){
Criteria criteria = getSession().createCriteria(getEntityClass());
for (Map.Entry<String, Object> entry : nameValuePairs.entrySet()) {
criteria.add(Restrictions.eq(entry.getKey(), entry.getValue()));
}
List<T> list = criteria.list();
return list;
}
@Override
@SuppressWarnings("unchecked")
public List<T> getAll() {
return getSession().createCriteria(getEntityClass()).list();
}
@Override
@SuppressWarnings("unchecked")
public T getUniqueResult(Map<String, Object> nameValuePairs) {
Criteria criteria = getSession().createCriteria(getEntityClass());
for (Map.Entry<String, Object> entry : nameValuePairs.entrySet()) {
criteria.add(Restrictions.eq(entry.getKey(), entry.getValue()));
}
return (T) criteria.uniqueResult();
}
@Override
@SuppressWarnings("unchecked")
public T load(Serializable id){
return (T) getSession().load(getEntityClass(), id);
}
@Override
public Serializable save(T t) {
return getSession().save(t);
}
@Override
public void update(T t) {
Session session = this.getSession();
session.update(t);
//強制刷新緩存中數據至數據庫中,防止大批量數據更新之后出現臟數據
session.flush();
}
@Override
public void delete(T t) {
this.getSession().delete(t);
}
/**
- QO DtoResultWithPageInfo<dtoClazz>list+??
- @param page
- @param pageSize
- @param qo
- @param dtoClazz
@return
/
/ public <Q extends QueryObject, D extends Dto> DtoResultWithPageInfo<D> queryPageListByQueryObject(
int page, int pageSize,Q qo, Class<D> dtoClazz){
Criteria criteria = QueryObjectHelper.buildCriteria(qo, getSession());
return queryPageListByCriteria(criteria, page, pageSize, dtoClazz);
}*/
/**
- QO List<dtoClazz>
- @param qo
- @param dtoClazz
@return
/
/public <Q extends QueryObject,E, D extends Dto> List<D> queryListByQueryObject(
Q qo, Class<D> dtoClazz){
Criteria criteria = QueryObjectHelper.buildCriteria(qo, getSession());
@SuppressWarnings("unchecked")
List<E> list = criteria.list();
List<D> resultsDtoList = new ArrayList<D>();
for(E entity:list){
try {
D dto = dtoClazz.newInstance();
BeanUtils.copyProperties(entity, dto);
resultsDtoList.add(dto);
} catch (InstantiationException e) {
log.error("dto??ExMsg==>"+e.getMessage());
} catch (IllegalAccessException e) {
log.error("dto??ExMsg==>"+e.getMessage());
}
}
return resultsDtoList;
}*/
/**
- queryPageListByCriteria
- ?criteria DtoResultWithPageInfo<dtoClazz>list+??
- @param criteria
- ?
- @param pageNo
- ??
- @param pageSize
- ???
- @param dtoClass
- ??class
/
/public <E, D extends Dto> DtoResultWithPageInfo<D> queryPageListByCriteria(
Criteria criteria, int pageNo, int pageSize, Class<D> dtoClazz) {
PageInfo pageInfo = getInstancePageInfoWithCriteria(criteria, pageNo,
pageSize);
criteria.setProjection(null);// ??
criteria.setFirstResult(pageInfo.getFirstResultNum());
criteria.setMaxResults(pageInfo.getPageSize());
@SuppressWarnings("unchecked")
List<E> resultsList = criteria.list();
List<D> resultsDtoList = new ArrayList<D>();
for (E result : resultsList) {
D dto;
try {
dto = dtoClazz.newInstance();
try {
BeanUtils.copyProperties(result, dto);
} catch (Exception e) {
log.error("???bean?");
e.printStackTrace();
}
} catch (InstantiationException e) {
log.error("???dto??");
e.printStackTrace();
dto = null;
} catch (IllegalAccessException e) {
log.error("???dto??");
e.printStackTrace();
dto = null;
}
resultsDtoList.add(dto);
}
DtoResultWithPageInfo<D> resultWithPageInfo = new DtoResultWithPageInfo<D>(
resultsDtoList, pageInfo);
return resultWithPageInfo;
}*/
/**
- ?criteria List<dtoClazz>
- @param criteria
- @param dtoClazz
@return
/
/public <E, D extends Dto> List<D> queryListByCriteria(
Criteria criteria,Class<D> dtoClazz) {
@SuppressWarnings("unchecked")
List<E> resultsList = criteria.list();
List<D> resultsDtoList = new ArrayList<D>();
for (E result : resultsList) {
D dto;
try {
dto = dtoClazz.newInstance();
try {
BeanUtils.copyProperties(result, dto);
} catch (Exception e) {
log.error("???bean?");
e.printStackTrace();
}
} catch (InstantiationException e) {
log.error("???dto??");
e.printStackTrace();
dto = null;
} catch (IllegalAccessException e) {
log.error("???dto??");
e.printStackTrace();
dto = null;
}
resultsDtoList.add(dto);
}
return resultsDtoList;
}*/
/*public DataTablePageList queryDataTablePageListByCriteria(
Criteria criteria, String displayStart, String displayLength) {
// ??
long totalRecords = 0L;
criteria.setProjection(Projections.rowCount());
totalRecords = (Long) criteria.uniqueResult();
//
criteria.setProjection(null);
criteria.setFirstResult(Integer.parseInt(displayStart));
criteria.setMaxResults(Integer.parseInt(displayLength));
@SuppressWarnings("rawtypes")
List resultsList = criteria.list();
DataTablePageList dtpl = new DataTablePageList(
String.valueOf((int) totalRecords), resultsList);
return dtpl;
}
*/
/**
- ?????
- @param criteria
- @param pageNo
- @param pageSize
@return
//
private PageInfo getInstancePageInfoWithCriteria(Criteria criteria,
int pageNo, int pageSize) {
long totalQuantity = 0L;
criteria.setProjection(Projections.rowCount());
totalQuantity = (Long) criteria.uniqueResult();
PageInfo pageInfo = PageInfo.getInstance(pageNo, pageSize,
totalQuantity);
return pageInfo;
}*/
@Override
public Criteria createCriteria() {
// TODO Auto-generated method stub
return getSession().createCriteria(getEntityClass());
}
/**
- queryPageListByCriteria
- ?criteria DtoResultWithPageInfo<dtoClazz>list+??
- @param criteria
- ?
- @param pageNo
- ??
- @param pageSize
- ???
- @param dtoClass
- ??class
- ? DtoResultWithPageInfo
? queryPageListByCriteria
*/
@Override
public <E, D extends Dto> DtoResultWithPageInfo<D> queryPageListByCriteria(
Criteria criteria, int pageNo, int pageSize, Class<D> dtoClazz) {
//???pageinfo?firstResult maxresult
PageInfo pageInfo = getInstancePageInfoWithCriteria(criteria, pageNo,
pageSize);
criteria.setProjection(null);// ??
criteria.setFirstResult(pageInfo.getFirstResultNum());
criteria.setMaxResults(pageInfo.getPageSize());
@SuppressWarnings("unchecked")
List<E> resultsList = criteria.list();
List<D> resultsDtoList = new ArrayList<D>();
for (E result : resultsList) {
D dto;
try {
dto = dtoClazz.newInstance();
try {
BeanUtils.copyProperties(result, dto);
} catch (Exception e) {
log.error("???bean?");
e.printStackTrace();
}
} catch (InstantiationException e) {
log.error("???dto??");
e.printStackTrace();
dto = null;
} catch (IllegalAccessException e) {
log.error("???dto??");
e.printStackTrace();
dto = null;
}
resultsDtoList.add(dto);
}
DtoResultWithPageInfo<D> resultWithPageInfo = new DtoResultWithPageInfo<D>(
resultsDtoList, pageInfo);
return resultWithPageInfo;
}
/**
- queryPageListByCriteriaWithQo
- ?criteria DtoResultWithPageInfo<dtoClazz>list+??
- @param criteria
- ?
- @param pageNo
- ??
- @param pageSize
- ???
- @param dtoClass
- ??class
- ? DtoResultWithPageInfo
? queryPageListByCriteria
*/
@Override
public <E, D extends Dto> DtoResultWithPageInfo<D> queryPageListByCriteriaWithQo(PageQo qo, Class<D> dtoClazz) {
//???pageinfo?firstResult maxresult
Criteria criteria = this.createCriteria();
qo.add(criteria);
PageInfo pageInfo = getInstancePageInfoWithCriteria(criteria, qo.getPage(),qo.getRows());
criteria.setProjection(null);// ??
criteria.setFirstResult(pageInfo.getFirstResultNum());
criteria.setMaxResults(pageInfo.getPageSize());
@SuppressWarnings("unchecked")
List<E> resultsList = criteria.list();
List<D> resultsDtoList = new ArrayList<D>();
for (E result : resultsList) {
D dto;
try {
dto = dtoClazz.newInstance();
try {
BeanUtils.copyProperties(result, dto);
} catch (Exception e) {
log.error("???bean?");
e.printStackTrace();
}
} catch (InstantiationException e) {
log.error("???dto??");
e.printStackTrace();
dto = null;
} catch (IllegalAccessException e) {
log.error("???dto??");
e.printStackTrace();
dto = null;
}
resultsDtoList.add(dto);
}
DtoResultWithPageInfo<D> resultWithPageInfo = new DtoResultWithPageInfo<D>(
resultsDtoList, pageInfo);
return resultWithPageInfo;
}
/**
- ?????
- @param criteria
- @param pageNo
- @param pageSize
@return
*/
private PageInfo getInstancePageInfoWithCriteria(Criteria criteria,
int pageNo, int pageSize) {
long totalQuantity = 0L;
// ?totalQuality
criteria.setProjection(Projections.rowCount());
totalQuantity = (Long) criteria.uniqueResult();
PageInfo pageInfo = PageInfo.getInstance(pageNo, pageSize,
totalQuantity);
return pageInfo;
}
}</code></pre>
這個方法是極為重要的 protected abstract Class<?> getEntityClass();
后續介紹,現在暫時有個印象。
在www中的dao層有與各具體類(數據表)相對應的數據庫操作實現:

上圖聲明了三個具體類對應的接口聲明:AdminDao、MacDao、TaskDao。
對應三個接口有三個具體的實現類:AdminDaoImpl、MacDaoImpl、TaskDaoImpl。
我們以與Admin類相關的dao層操作為例:
Admin.java
package com.fxmms.www.domain;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
/**
- Created by mark on 16/11/2.
@usage 管理員實體類,與數據庫中表相對應
*/
@Entity
@Table(name = "mms_admin")
public class Admin {
@Id
@GeneratedValue(generator = "increment")
@GenericGenerator(name = "increment", strategy = "increment")
@Column
private int id;
@Column
private String userName;
@Column
private String password;
@Column
private String role;
@Column
private int enable;
@Column
private int isDelete;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public int getEnable() {
return enable;
}
public void setEnable(int enable) {
this.enable = enable;
}
public int getIsDelete() {
return isDelete;
}
public void setIsDelete(int isDelete) {
this.isDelete = isDelete;
}
}</code></pre>
AdminDao.java
package com.fxmms.www.dao;
import com.fxmms.common.dao.BaseDao;
import com.fxmms.www.domain.Admin;
/**
- Created by mark on 16/10/31.
- @usage 操作管理員數據庫訪問接口
*/
public interface AdminDao extends BaseDao<Admin> {
}</code></pre>
AdminDaoImpl.java
package com.fxmms.www.dao.hib;
import com.fxmms.common.dao.hib.HibernateTemplateDao;
import com.fxmms.www.dao.AdminDao;
import com.fxmms.www.domain.Admin;
/**
- Created by mark on 16/11/2.
@usage 使用適配器模式,將common層中定義的公共訪問數據庫方法實現嫁接到Admin類的接口中。
*/
public class AdminDaoImpl extends HibernateTemplateDao<Admin> implements AdminDao {
@Override
protected Class<?> getEntityClass() {
// TODO Auto-generated method stub
return Admin.class;
}
}</code></pre>
可以看到,在具體類相關的數據庫操作實現類中,我們只需要實現HibernateTemplateDao<T>中抽象方法protected Class<?> getEntityClass();即可。
給我們的感覺就是這個方法的實現是畫龍點睛之筆。
回過頭去看,在HibernateTemplateDao類中所有與數據庫操作有關的方法:
例如:
@Override
@SuppressWarnings("unchecked")
public T getByUniqueKey(String columnName, Object value) {
return (T) getSession().createCriteria(getEntityClass())
.add(Restrictions.eq(columnName, value)).uniqueResult();
}
getEntityClass()方法最終都會被具體的類所實現。這個設計真的是很巧妙。
5.配置tomcat 運行環境
項目搭建已經完畢,接下來需要做的就是配置項目的運行環境了,這里我們采用tomcat來充當應用服務器。
5.1 去官網下載 tomcat 8.0 :
5.2 配置 tomcat 服務器:
點擊Edit Configurations

點擊 + ,并選擇Tomcat Server中local選項

添加啟動任務名稱,默認為unnamed

配置Application Server

裝載開發版(exploded)應用war包,此步驟有兩種方式:
第一種方式:選擇Deploy at the server startup下方的 + ,入下圖所示:

接下來在Select Artifacts Deploy 彈出框中 選擇 exploded 屬性的war包

接下來選擇apply-> ok ,最終的結果是:


最終點擊啟動按鈕啟動應用

最終的啟動效果如下所示

6.webapp文件夾下分層詳解
webapp下有res文件夾,用于存儲靜態文件,WEB-INF文件夾下有view文件夾表示
關于項目中應用到的JNI技術,會在后面講解,主要側重點是在代碼層面解決JNI link library的問題。
來自:http://www.jianshu.com/p/25039d901ac2