Java 本地開(kāi)發(fā)環(huán)境搭建
項(xiàng)目搭建采用技術(shù)棧為:Spring+Spring MVC+Hibernate+Jsp+Gradle+tomcat+mysql5.6
搭建環(huán)境文檔目錄結(jié)構(gòu)說(shuō)明:
- 使用Intellj Idea 搭建項(xiàng)目過(guò)程詳解
- 項(xiàng)目各配置文件講解及部署
- 各層包功能講解&項(xiàng)目搭建完畢最終效果演示圖
- 項(xiàng)目中重要代碼講解
- webapp文件夾下分層詳解
- 配置tomcat 運(yùn)行環(huán)境
7.福利彩蛋
1. 使用Intellj Idea 搭建項(xiàng)目過(guò)程詳解
1.1 打開(kāi)Intellj Idea
1.2 操縱 Intellj Idea 工具欄 新建項(xiàng)目
需要說(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àn)如下視圖:
接下來(lái):?jiǎn)螕鬽ain文件夾按照如下操作:
點(diǎn)擊ok,再按照上圖操作操作一遍削咆,輸入文件名為resources
最終的結(jié)構(gòu)圖如下圖所示:
2. 項(xiàng)目各配置文件講解及部署
完成了項(xiàng)目的初始化結(jié)構(gòu)創(chuàng)建,接下來(lái)我們需要來(lái)創(chuàng)建配置文件蠢笋。
首先是resources文件夾下的配置文件
2.1 resources下資源文件截圖:(最終配置的結(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)如下圖所示:
對(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):
上圖聲明了三個(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)如下圖所示:
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.0:http://tomcat.apache.org/download-80.cgi
6.2 配置 tomcat 服務(wù)器:
點(diǎn)擊Edit Configurations
點(diǎn)擊+,并選擇Tomcat Server中l(wèi)ocal選項(xiàng)
添加啟動(dòng)任務(wù)名稱(chēng)辽剧,默認(rèn)為unnamed
配置Application Server
裝載開(kāi)發(fā)版(exploded)應(yīng)用war包,此步驟有兩種方式:
第一種方式:選擇Deploy at the server startup下方的+,入下圖所示:
接下來(lái)在Select Artifacts Deploy 彈出框中 選擇 exploded 屬性的war包
接下來(lái)選擇apply-> ok 税产,最終的結(jié)果是:
最終點(diǎn)擊啟動(dòng)按鈕啟動(dòng)應(yīng)用
最終的啟動(dòng)效果如下所示
模板代碼地址: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í)操;
掃碼就可以添加哦~
博客搬家:大坤的個(gè)人博客
歡迎評(píng)論哦~