使用Intellij Idea+Gradle 搭建Java 本地開(kāi)發(fā)環(huán)境

Java 本地開(kāi)發(fā)環(huán)境搭建


項(xiàng)目搭建采用技術(shù)棧為:Spring+Spring MVC+Hibernate+Jsp+Gradle+tomcat+mysql5.6

搭建環(huán)境文檔目錄結(jié)構(gòu)說(shuō)明:

  1. 使用Intellj Idea 搭建項(xiàng)目過(guò)程詳解
  2. 項(xiàng)目各配置文件講解及部署
  3. 各層包功能講解&項(xiàng)目搭建完畢最終效果演示圖
  4. 項(xiàng)目中重要代碼講解
  5. webapp文件夾下分層詳解
  6. 配置tomcat 運(yùn)行環(huán)境
    7.福利彩蛋

1. 使用Intellj Idea 搭建項(xiàng)目過(guò)程詳解


1.1 打開(kāi)Intellj Idea

Intellj idea 截圖

1.2 操縱 Intellj Idea 工具欄 新建項(xiàng)目

操縱idea 工具欄
使用Gradle創(chuàng)建項(xiàng)目
完善項(xiàng)目信息
設(shè)置Gradle
確定項(xiàng)目信息
選擇New Window
初始化項(xiàng)目結(jié)構(gòu)截圖

需要說(shuō)明的是凸主,最初創(chuàng)建的項(xiàng)目視圖是不完整的凑保,包括webapp文件夾下沒(méi)有web.xml交胚,以及src包下缺少Java文件夾(放置java源代碼文件)刁岸,Resources文件夾(放置項(xiàng)目配置文件)。
我們繼續(xù)做以下操作鹃唯,使得項(xiàng)目的結(jié)構(gòu)符合web 應(yīng)用項(xiàng)目的層級(jí)標(biāo)準(zhǔn)搔耕。

操縱工具欄為項(xiàng)目添加 web.xml全局配置文件

出現(xiàn)如下視圖:

新建 web.xml文件
設(shè)置web.xml文件存儲(chǔ)位置

接下來(lái):?jiǎn)螕鬽ain文件夾按照如下操作:


手動(dòng)創(chuàng)建src中main文件夾下java目錄
輸入java 文件夾名稱(chēng)

點(diǎn)擊ok,再按照上圖操作操作一遍削咆,輸入文件名為resources
最終的結(jié)構(gòu)圖如下圖所示:

項(xiàng)目最終結(jié)構(gòu)圖

2. 項(xiàng)目各配置文件講解及部署


完成了項(xiàng)目的初始化結(jié)構(gòu)創(chuàng)建,接下來(lái)我們需要來(lái)創(chuàng)建配置文件蠢笋。
首先是resources文件夾下的配置文件
2.1 resources下資源文件截圖:(最終配置的結(jié)果)

項(xiàng)目所需配置文件最終配置結(jié)果

2.2 data-access-applicationContext.xml
主要管理數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)組件

<?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"
       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
       ">

    <!-- 配置自動(dòng)掃描的包 -->
    <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>

    <!-- 配置數(shù)據(jù)源 -->
    <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>
                <!--負(fù)責(zé)自動(dòng)創(chuàng)建數(shù)據(jù)表拨齐,基本上不能打開(kāi)注釋?zhuān)駝t所有的數(shù)據(jù)庫(kù)中表信息都會(huì)被刪除,重新創(chuàng)建-->
                <!-- <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 數(shù)據(jù) -->
    <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>
         <!–使用二級(jí)緩存–>
         <property name="sharedCacheMode" value="ENABLE_SELECTIVE"></property>
     </bean>

     <!– 配置事務(wù) –>
     <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>

2.3 service-applicationContext.xml
主要管理業(yè)務(wù)邏輯組件昨寞,包括對(duì)數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)的事務(wù)控制瞻惋,以及定時(shí)任務(wù)。

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:task="http://www.springframework.org/schema/task"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/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
        http://www.springframework.org/schema/task/spring-task.xsd">

    <aop:aspectj-autoproxy/>

    <!--設(shè)置定時(shí)任務(wù)-->
    <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>

2.4 default-servlet.xml
設(shè)置springmvc-applicationContext.xml,前端控制器將請(qǐng)求轉(zhuǎn)發(fā)到相應(yīng)的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>
    <!--因?yàn)閣eb.xml中defaultDispatcherServlet對(duì)所有請(qǐng)求進(jìn)行了攔截熟史,所以對(duì)一些.css .jpg .html .jsp也進(jìn)行了攔截,所以此配置項(xiàng)
    保證對(duì)對(duì)靜態(tài)資源不攔截-->
    <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
設(shè)置spring-security 權(quán)限控制配置文件窄俏,項(xiàng)目中權(quán)限的控制統(tǒng)一在此配置文件中配置,包括從數(shù)據(jù)庫(kù)中獲取用戶(hù)的相關(guān)信息碘菜,以及配置相應(yīng)pattern的請(qǐng)求過(guò)濾規(guī)則凹蜈。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="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
        http://www.springframework.org/schema/security/spring-security-3.2.xsd">
    <!--    <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" /><!– 不過(guò)濾驗(yàn)證碼 –>
        <sec:http pattern="/test/**" security="none"></sec:http><!– 不過(guò)濾測(cè)試內(nèi)容 –>-->
    <!--spring security 權(quán)限管理配置文件-->
    <context:component-scan base-package="com.fxmms.common.security">
    </context:component-scan>
    <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
    <!--權(quán)限控制-->
    <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')"/>
        <!--自定義登陸頁(yè)面,權(quán)限驗(yàn)證失敗頁(yè)面限寞,登錄成功頁(yè)面-->
        <sec:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp" login-processing-url="/j_spring_security_check"
                        authentication-success-handler-ref="loginSuccessHandler"/>
        <!--用戶(hù)權(quán)限不一致出現(xiàn)的權(quán)限不可得情況,默認(rèn)情況下跳轉(zhuǎn)到403頁(yè)面-->
        <sec:access-denied-handler ref="accessDeniedServletHandler" />
        <sec:logout logout-success-url="/login.jsp" />
    </sec:http>

    <sec:authentication-manager>
        <sec:authentication-provider>
            <!--配置從數(shù)據(jù)庫(kù)查詢(xún)用戶(hù)權(quán)限  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>

2.6 db.properties
數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)配置文件

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

2.7 log4j.properties
配置項(xiàng)目日志文件仰坦,日志輸出模式為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,D,E

#配置stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss,SSS} [%p]-[%l] %m%n

#配置D 保存info debug級(jí)別的系統(tǒng)日志信息
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
#/Users/mark/mms/log.log 指定info debug級(jí)別日志信息存儲(chǔ)位置
log4j.appender.D.File = /Users/mark/mms/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = INFO,DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %d{yyyy-MM-dd HH\:mm\:ss,SSS} [%p]-[%l] %m%n

#配置E 保存系統(tǒng)異常日志 
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
#/Users/mark/mms/error.log 指定info debug級(jí)別日志信息存儲(chǔ)位置
log4j.appender.E.File = /Users/mark/mms/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %d{yyyy-MM-dd HH\:mm\:ss,SSS} [%p]-[%l] %m%n

#log4j.logger.org.hibernate=INFO
#
## Log all JDBC parameters
#log4j.logger.org.hibernate.type=ALL

##Hibernate begin 打印每次數(shù)據(jù)訪(fǎng)問(wèn)產(chǎn)生的sql語(yǔ)句至log.log 文件當(dāng)中##
log4j.logger.org.hibernate=info
#配置SQL打印與輸出
log4j.logger.org.hibernate.SQL=DEBG
log4j.logger.org.hibernate.HQL=DEGUG
#log4j.logger.org.hibernate.type=ALL

2.8 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <!--配置需要加載的spring配置文件履植,這些文件中的配置的類(lèi)都是被<context:component-scan>掃描到的,比如@Repository @Component
    @Service @Controller等-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:data-access-applicationContext.xml;classpath:spring-security.xml;classpath:service-applicationContext.xml</param-value>
    </context-param>
    <!--配置日志監(jiān)聽(tīng) 悄晃,如果配置文件報(bào)紅玫霎,沒(méi)有關(guān)系可以正常運(yùn)行,這個(gè)與idea的驗(yàn)證規(guī)則有關(guān)-->
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>classpath:log4j.properties</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

   <!--配置權(quán)限過(guò)濾器妈橄,注意必須配置在springmvc 之前庶近,因?yàn)閷?duì)用戶(hù)訪(fǎng)問(wèn)資源的權(quán)限判斷與控制是在訪(fǎng)問(wèn)特定url之前發(fā)生的-->
    <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>

    <!-- 配置字符編碼過(guò)濾器  必須配置在所有過(guò)濾器的最前面 -->
    <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>
    <!--超級(jí)管理員 -->
  <!-- <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請(qǐng)求轉(zhuǎn)為PUT,DELETE請(qǐng)求的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>
    <!--配置中央控制器眷蚓,對(duì)所有請(qǐng)求進(jìn)行攔截并做請(qǐng)求路徑鼻种,與處理請(qǐng)求樁模塊之間的映射-->
    <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>

2.9 build.gradle
項(xiàng)目構(gòu)建腳本

group 'com.fxmms'
version '1.0-SNAPSHOT'

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'war'
sourceCompatibility = 1.8

repositories {
    maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
    mavenLocal()
    jcenter()
    maven { url "http://repo.maven.apache.org/maven2/"}
    maven { url 'https://repo.spring.io/libs-milestone'}
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    // servlet-api
    compile group: 'javax.servlet', name: 'servlet-api', version: '2.5'
    //spring相關(guān)
    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相關(guān)
    compile 'org.hibernate:hibernate-core:4.3.6.Final'
    //c3p0連接池
    compile group: 'org.hibernate', name: 'hibernate-c3p0', version: '4.3.6.Final'
    //ehcahe二級(jí)緩存
    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解析相關(guān)
    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'
    //迅雷接口有關(guān)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 讀取文件相關(guān)
    compile group: 'org.apache.commons', name: 'commons-io', version: '1.3.2'
    // https://mvnrepository.com/artifact/org.apache.poi/poi 文件讀取相關(guān) 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'
}

3. 各層包功能講解&項(xiàng)目搭建完畢最終效果演示圖


3.1 項(xiàng)目中各層包功能講解
項(xiàng)目中Java源代碼層級(jí)結(jié)構(gòu)如下圖所示:

項(xiàng)目中Java源代碼層級(jí)結(jié)構(gòu)

對(duì)于www包中的各分層,我們對(duì)照上圖重點(diǎn)說(shuō)明:

controller:用于路由各種HTTP訪(fǎng)問(wèn)沙热,其中可以實(shí)現(xiàn)對(duì)前臺(tái)頁(yè)面參數(shù)的對(duì)象化綁定叉钥,這個(gè)功能的實(shí)現(xiàn)是依賴(lài)于spring mvc中的參數(shù)綁定功能,以及返回向前端頁(yè)面返回?cái)?shù)據(jù)篙贸。也可以實(shí)現(xiàn)基于Restful 風(fēng)格API的編寫(xiě)投队。
dao:用于實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的操作,包中的代碼繼承并實(shí)現(xiàn)自common中的dao 層代碼爵川,采用的是類(lèi)的適配器模式實(shí)現(xiàn)的蛾洛,這里的代碼值得細(xì)細(xì)品味,可以說(shuō)是整個(gè)項(xiàng)目的靈魂所在之處雁芙,稍后說(shuō)明轧膘。
domain:項(xiàng)目中的所有實(shí)體類(lèi)都存在于這個(gè)包中,其中的每個(gè)具體實(shí)體類(lèi)與數(shù)據(jù)庫(kù)表相對(duì)應(yīng)兔甘。
dto:實(shí)現(xiàn)了序列化的數(shù)據(jù)傳輸層對(duì)象谎碍,可用于接收前臺(tái)參數(shù),前臺(tái)參數(shù)被封裝成dto 對(duì)象傳輸至后臺(tái)洞焙。同時(shí)也負(fù)責(zé)對(duì)從數(shù)據(jù)庫(kù)中查詢(xún)數(shù)據(jù)的封裝蟆淀。
qo:模糊查詢(xún)對(duì)象所在的包,用于封裝QBC動(dòng)態(tài)查詢(xún)參數(shù)澡匪。
rowmapper:用于映射jdbcTemplate查詢(xún)數(shù)據(jù)庫(kù)返回對(duì)象的數(shù)據(jù)集熔任,并將數(shù)據(jù)集依照以此對(duì)象為集合的實(shí)例進(jìn)行封裝。
schedulejob:定時(shí)任務(wù)類(lèi)所在的包唁情,在此包中的類(lèi)上都要加上@Service注解疑苔,因?yàn)槎〞r(shí)任務(wù)注解配置在service-applicationContext.xml中,包掃描組件的規(guī)則是只掃描類(lèi)上有@Service注解的組件類(lèi)甸鸟。
service:業(yè)務(wù)邏輯層惦费,所有的業(yè)務(wù)邏輯組件Bean都放置在這個(gè)保重兵迅,其中的類(lèi)中的業(yè)務(wù)邏輯方法調(diào)用了dao實(shí)現(xiàn)類(lèi)中的方法,并且每個(gè)有關(guān)于數(shù)據(jù)庫(kù)操作的方法上都加上了@Transaction注解薪贫,用于實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)操作的事務(wù)管理恍箭。@Transaction是Spring Framework對(duì)AOP 的另一種區(qū)別于攔截器的自定義注解實(shí)現(xiàn)。

4.項(xiàng)目中重要代碼講解


主要講解一下Dao層中代碼對(duì)適配器設(shè)計(jì)模式的應(yīng)用:
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  數(shù)據(jù)庫(kù)公共操作接口
 */
@Repository
public interface BaseDao<T> {

 /**
  *
  * 
  * @param id
  * @usage 根據(jù)id獲取數(shù)據(jù)庫(kù)中唯一紀(jì)錄瞧省,封裝成java對(duì)象并返回
  * @return T
  */
 public T getById(Serializable id);

 /**
  * 
  * 
  * @param id
  * @usage 根據(jù)id懶加載數(shù)據(jù)庫(kù)中唯一紀(jì)錄扯夭,封裝成java對(duì)象并返回
  * @return T
  */
 public T load(Serializable id);

 /**
  * 
  * 
  * @param columnName
  *            
  * @param value
  *
  * @usage 根據(jù)列名,以及對(duì)應(yīng)的值獲取數(shù)據(jù)庫(kù)中惟一紀(jì)錄鞍匾,封裝成Java對(duì)象并返回
  *          
  * @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);

}

其中定義了一些對(duì)數(shù)據(jù)庫(kù)的抽象公共操作方法交洗,代碼中有注釋?zhuān)梢詫?duì)照理解。

4.2 看下HibernateTemplateDao.java對(duì)BaseDao.java的抽象實(shí)現(xiàn)

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 應(yīng)用數(shù)據(jù)訪(fǎng)問(wèn)的靈魂候学,抽象出各種模型類(lèi)進(jìn)行數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)的公共操作藕筋。
 *        主要使用到QBC動(dòng)態(tài)查詢(xún)。主要思想是利用反射梳码。
 */
@Repository
public abstract class HibernateTemplateDao<T> implements BaseDao<T> {
 protected static final Log log = LogFactory
   .getLog(HibernateTemplateDao.class);
    //通過(guò)反射隐圾,可以實(shí)現(xiàn)對(duì)不同類(lèi)對(duì)應(yīng)的數(shù)據(jù)表的操作
 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);
  //強(qiáng)制刷新緩存中數(shù)據(jù)至數(shù)據(jù)庫(kù)中,防止大批量數(shù)據(jù)更新之后出現(xiàn)臟數(shù)據(jù)
  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;
 }
}

這個(gè)方法是極為重要的 protected abstract Class<?> getEntityClass();
后續(xù)介紹掰茶,現(xiàn)在暫時(shí)有個(gè)印象暇藏。
在www中的dao層有與各具體類(lèi)(數(shù)據(jù)表)相對(duì)應(yīng)的數(shù)據(jù)庫(kù)操作實(shí)現(xiàn):

屏幕快照 2016-11-20 下午11.22.30.png

上圖聲明了三個(gè)具體類(lèi)對(duì)應(yīng)的接口聲明:AdminDao、MacDao濒蒋、TaskDao盐碱。
對(duì)應(yīng)三個(gè)接口有三個(gè)具體的實(shí)現(xiàn)類(lèi):AdminDaoImpl、MacDaoImpl沪伙、TaskDaoImpl瓮顽。
我們以與Admin類(lèi)相關(guān)的dao層操作為例:
Admin.java

package com.fxmms.www.domain;

import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;

/**
 * Created by mark on 16/11/2.
 * @usage 管理員實(shí)體類(lèi),與數(shù)據(jù)庫(kù)中表相對(duì)應(yīng)
 */
@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;
    }
}

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 操作管理員數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)接口
 */
public interface AdminDao extends BaseDao<Admin> {

}

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層中定義的公共訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)方法實(shí)現(xiàn)嫁接到Admin類(lèi)的接口中暖混。
 */
public class AdminDaoImpl extends HibernateTemplateDao<Admin> implements AdminDao {

    @Override
    protected Class<?> getEntityClass() {
        // TODO Auto-generated method stub
        return Admin.class;
    }
}

可以看到,在具體類(lèi)相關(guān)的數(shù)據(jù)庫(kù)操作實(shí)現(xiàn)類(lèi)中翁授,我們只需要實(shí)現(xiàn)HibernateTemplateDao<T>中抽象方法protected Class<?> getEntityClass()拣播;即可。
給我們的感覺(jué)就是這個(gè)方法的實(shí)現(xiàn)是畫(huà)龍點(diǎn)睛之筆收擦。
回過(guò)頭去看贮配,在HibernateTemplateDao類(lèi)中所有與數(shù)據(jù)庫(kù)操作有關(guān)的方法:
例如:

 @Override
 @SuppressWarnings("unchecked")
 public T getByUniqueKey(String columnName, Object value) {
  return (T) getSession().createCriteria(getEntityClass())
    .add(Restrictions.eq(columnName, value)).uniqueResult();
 }

getEntityClass()方法最終都會(huì)被具體的類(lèi)所實(shí)現(xiàn)。這個(gè)設(shè)計(jì)真的是很巧妙塞赂。

5.webapp文件夾下分層詳解


webapp下有res文件夾泪勒,用于存儲(chǔ)靜態(tài)文件,WEB-INF文件夾下有view文件夾用于放置應(yīng)用中jsp頁(yè)面。
文件組織結(jié)構(gòu)如下圖所示:

webapp下靜態(tài)資源以及前端頁(yè)面

6.配置tomcat 運(yùn)行環(huán)境


項(xiàng)目搭建已經(jīng)完畢酣藻,接下來(lái)需要做的就是配置項(xiàng)目的運(yùn)行環(huán)境了曹洽,這里我們采用tomcat來(lái)充當(dāng)應(yīng)用服務(wù)器鳍置。
6.1 去官網(wǎng)下載tomcat 8.0http://tomcat.apache.org/download-80.cgi
6.2 配置 tomcat 服務(wù)器:
點(diǎn)擊Edit Configurations

屏幕快照 2016-11-20 下午11.48.58.png

點(diǎn)擊+,并選擇Tomcat Server中l(wèi)ocal選項(xiàng)
屏幕快照 2016-11-20 下午11.51.03.png

添加啟動(dòng)任務(wù)名稱(chēng)辽剧,默認(rèn)為unnamed
屏幕快照 2016-11-21 上午9.33.39.png

配置Application Server
屏幕快照 2016-11-21 上午9.39.06.png

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

屏幕快照 2016-11-21 上午9.54.16.png

接下來(lái)在Select Artifacts Deploy 彈出框中 選擇 exploded 屬性的war包


屏幕快照 2016-11-21 上午9.54.31.png

接下來(lái)選擇apply-> ok 税产,最終的結(jié)果是:

屏幕快照 2016-11-21 上午10.05.46.png
屏幕快照 2016-11-21 上午10.12.55.png

最終點(diǎn)擊啟動(dòng)按鈕啟動(dòng)應(yīng)用


屏幕快照 2016-11-21 上午10.15.46.png

最終的啟動(dòng)效果如下所示

屏幕快照 2016-11-21 上午10.27.45.png

模板代碼地址:https://coding.net/u/zongyuan/p/Java-backend-template/git
關(guān)于項(xiàng)目中應(yīng)用到的JNI技術(shù)怕轿,會(huì)在后面講解,主要側(cè)重點(diǎn)是在代碼層面解決JNI link library的問(wèn)題辟拷。

關(guān)于公眾號(hào)

精進(jìn)撞羽!
道友們,你們好衫冻。早前個(gè)人就有開(kāi)設(shè)公眾號(hào)的念想诀紊,今年10月終于開(kāi)搞了。
我的個(gè)人的 訂閱號(hào)--T客來(lái)了隅俘;
平時(shí)自己會(huì)總結(jié)一些后端開(kāi)發(fā)相關(guān)的技術(shù)邻奠;
最近也迷上了音視頻開(kāi)發(fā)相關(guān)技術(shù);

技術(shù)分享包括:

  • 1.FFmpeg 工程實(shí)戰(zhàn)为居、
  • 2.數(shù)據(jù)庫(kù) MySQL原理與實(shí)戰(zhàn)碌宴、
  • 3.Redis中間件、
  • 4.Nginx蒙畴、Java并發(fā)編程贰镣、
  • 5.Go語(yǔ)言方面的技術(shù)知識(shí)與實(shí)操;


    T客來(lái)了

掃碼就可以添加哦~

博客搬家:大坤的個(gè)人博客
歡迎評(píng)論哦~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市膳凝,隨后出現(xiàn)的幾起案子碑隆,更是在濱河造成了極大的恐慌,老刑警劉巖蹬音,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件上煤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡祟绊,警方通過(guò)查閱死者的電腦和手機(jī)楼入,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)牧抽,“玉大人嘉熊,你說(shuō)我怎么就攤上這事⊙锸妫” “怎么了阐肤?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我孕惜,道長(zhǎng)愧薛,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任衫画,我火速辦了婚禮毫炉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘削罩。我一直安慰自己瞄勾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布弥激。 她就那樣靜靜地躺著进陡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪微服。 梳的紋絲不亂的頭發(fā)上趾疚,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音以蕴,去河邊找鬼糙麦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛舒裤,可吹牛的內(nèi)容都是我干的喳资。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼腾供,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼仆邓!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起伴鳖,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤节值,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后榜聂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體搞疗,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年须肆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了匿乃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡豌汇,死狀恐怖幢炸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拒贱,我是刑警寧澤宛徊,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布佛嬉,位于F島的核電站,受9級(jí)特大地震影響闸天,放射性物質(zhì)發(fā)生泄漏暖呕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一苞氮、第九天 我趴在偏房一處隱蔽的房頂上張望湾揽。 院中可真熱鬧,春花似錦葱淳、人聲如沸钝腺。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至定硝,卻和暖如春皿桑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蔬啡。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工诲侮, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人箱蟆。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓沟绪,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親空猜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子绽慈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,527評(píng)論 25 707
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)辈毯,斷路器坝疼,智...
    卡卡羅2017閱讀 134,601評(píng)論 18 139
  • 喬嶼/文 晚睡,其實(shí)是一種習(xí)慣谆沃。 也許我已經(jīng)把這種習(xí)慣當(dāng)成了一種態(tài)度钝凶。 一種我習(xí)慣生活的溫度。 也許我這個(gè)人腦子不...
    喬嶼Henry閱讀 812評(píng)論 22 62
  • 我曾走進(jìn)你的生命 在你還是少女的年代 我們整天談?wù)撝倌陸?yīng)有的趣事 語(yǔ)文考試 數(shù)學(xué)測(cè)驗(yàn) 還有誰(shuí)的作文又給老師當(dāng)做范...
    浮萍似夢(mèng)閱讀 140評(píng)論 0 1