使用Intellij Idea+Gradle 搭建Java 本地开发环境-阿里云开发者社区

开发者社区> markfork> 正文

使用Intellij Idea+Gradle 搭建Java 本地开发环境

简介: Java 本地开发环境搭建 项目搭建采用技术栈为:Spring+Spring MVC+Hibernate+Jsp+Gradle+tomcat+mysql5.
+关注继续查看

Java 本地开发环境搭建


项目搭建采用技术栈为:Spring+Spring MVC+Hibernate+Jsp+Gradle+tomcat+mysql5.6

搭建环境文档目录结构说明:

  1. 使用Intellj Idea 搭建项目过程详解
  2. 项目各配置文件讲解及部署
  3. 各层包功能讲解&项目搭建完毕最终效果演示图
  4. 项目中重要代码讲解
  5. webapp文件夹下分层详解
  6. 配置tomcat 运行环境
    7.福利彩蛋

1. 使用Intellj Idea 搭建项目过程详解


1.1 打开Intellj Idea

img_96c1e3c5847ae62b4aa86446e8cff4ce.png
Intellj idea 截图

1.2 操纵 Intellj Idea 工具栏 新建项目

img_18b6abae5de02bf04df3c82b71fb41f4.png
操纵idea 工具栏
img_b09e9d972ee04677e5f4d22735dfd653.png
使用Gradle创建项目
img_7b6fe26d05fbc68d5302553927d49fd5.png
完善项目信息
img_487dff81ceee0a37319e97163a3839eb.png
设置Gradle
img_c852326ed3d888e29692cdd6cf761c29.png
确定项目信息
img_35eadd696534adda85cf2aa43641446c.png
选择New Window
img_8fb408fb48c819d6e01e1a0ff5b8d845.png
初始化项目结构截图

需要说明的是,最初创建的项目视图是不完整的,包括webapp文件夹下没有web.xml,以及src包下缺少Java文件夹(放置java源代码文件),Resources文件夹(放置项目配置文件)。
我们继续做以下操作,使得项目的结构符合web 应用项目的层级标准。

img_b9d3d9b6cca0fb6508b56cbefdbce27e.png
操纵工具栏为项目添加 web.xml全局配置文件

出现如下视图:

img_ac06a44d57539aa81cdacacda50439b6.png
新建 web.xml文件
img_3d544b8982638a0ae91340074165fbdf.png
设置web.xml文件存储位置

接下来:单击main文件夹按照如下操作:


img_9832c6b495765e2fbe459cd6fc63f372.png
手动创建src中main文件夹下java目录
img_75fc2bfb6857235475f8599a61526435.png
输入java 文件夹名称

点击ok,再按照上图操作操作一遍,输入文件名为resources
最终的结构图如下图所示:

img_dc823722075f6b5fa0c53dbedb30836e.png
项目最终结构图

2. 项目各配置文件讲解及部署


完成了项目的初始化结构创建,接下来我们需要来创建配置文件。
首先是resources文件夹下的配置文件
2.1 resources下资源文件截图:(最终配置的结果)

img_5dfa49957f151c1013ec4f0f116be270.png
项目所需配置文件最终配置结果

2.2 data-access-applicationContext.xml
主要管理数据库访问组件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       ">

    <!-- 配置自动扫描的包 -->
    <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>

2.3 service-applicationContext.xml
主要管理业务逻辑组件,包括对数据库访问的事务控制,以及定时任务。

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns: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/>

    <!--设置定时任务-->
    <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
设置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"
       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" /><!– 不过滤验证码 –>
        <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>

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

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,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级别的系统日志信息
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
#/Users/mark/mms/log.log 指定info debug级别日志信息存储位置
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 保存系统异常日志 
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
#/Users/mark/mms/error.log 指定info debug级别日志信息存储位置
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 打印每次数据访问产生的sql语句至log.log 文件当中##
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配置文件,这些文件中的配置的类都是被<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>
    <!--配置日志监听 ,如果配置文件报红,没有关系可以正常运行,这个与idea的验证规则有关-->
    <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>

   <!--配置权限过滤器,注意必须配置在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>

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 "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相关
    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'
}

3. 各层包功能讲解&项目搭建完毕最终效果演示图


3.1 项目中各层包功能讲解
项目中Java源代码层级结构如下图所示:

img_28f41672259933d0a93ab5331ccdf9f3.png
项目中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:业务逻辑层,所有的业务逻辑组件Bean都放置在这个保重,其中的类中的业务逻辑方法调用了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);

}

其中定义了一些对数据库的抽象公共操作方法,代码中有注释,可以对照理解。

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;
 }
}

这个方法是极为重要的 protected abstract Class<?> getEntityClass();
后续介绍,现在暂时有个印象。
在www中的dao层有与各具体类(数据表)相对应的数据库操作实现:

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

上图声明了三个具体类对应的接口声明: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;
    }
}

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> {

}

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;
    }
}

可以看到,在具体类相关的数据库操作实现类中,我们只需要实现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.webapp文件夹下分层详解


webapp下有res文件夹,用于存储静态文件,WEB-INF文件夹下有view文件夹用于放置应用中jsp页面。
文件组织结构如下图所示:

img_ae40cca924de14848ce4eabba5f51bad.png
webapp下静态资源以及前端页面

6.配置tomcat 运行环境


项目搭建已经完毕,接下来需要做的就是配置项目的运行环境了,这里我们采用tomcat来充当应用服务器。
6.1 去官网下载tomcat 8.0http://tomcat.apache.org/download-80.cgi
6.2 配置 tomcat 服务器:
点击Edit Configurations

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

点击+,并选择Tomcat Server中local选项
img_9f153687f6928219cbe4fa923ca4fb2f.png
屏幕快照 2016-11-20 下午11.51.03.png

添加启动任务名称,默认为unnamed
img_44547e7853e5a740224dc0497dbc1722.png
屏幕快照 2016-11-21 上午9.33.39.png

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

装载开发版(exploded)应用war包,此步骤有两种方式:
第一种方式:选择Deploy at the server startup下方的+,入下图所示:

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

接下来在Select Artifacts Deploy 弹出框中 选择 exploded 属性的war包


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

接下来选择apply-> ok ,最终的结果是:

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

最终点击启动按钮启动应用


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

最终的启动效果如下所示

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

模板代码地址:https://coding.net/u/zongyuan/p/Java-backend-template/git
关于项目中应用到的JNI技术,会在后面讲解,主要侧重点是在代码层面解决JNI link library的问题。

福利彩蛋

职位:腾讯OMG 广告后台高级开发工程师;
Base:深圳;
场景:海量数据,To B,To C,场景极具挑战性。
基础要求:
熟悉常用数据结构与算法;
熟悉常用网络协议,熟悉网络编程;
熟悉操作系统,有线上排查问题经验;
熟悉MySQL,oracle;
熟悉JAVA,GoLang,c++其中一种语言均可;
可内推,欢迎各位优秀开发道友私信[微笑]
期待关注我的开发小哥哥,小姐姐们私信我,机会很好,平台对标抖音,广告生态平台,类似Facebook 广告平台,希望你们用简历砸我~
联系方式 微信 13609184526

博客搬家:大坤的个人博客
欢迎评论哦~

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
使用NAT网关轻松为单台云服务器设置多个公网IP
在应用中,有时会遇到用户询问如何使单台云服务器具备多个公网IP的问题。 具体如何操作呢,有了NAT网关这个也不是难题。
26502 0
阿里云服务器ECS远程登录用户名密码查询方法
阿里云服务器ECS远程连接登录输入用户名和密码,阿里云没有默认密码,如果购买时没设置需要先重置实例密码,Windows用户名是administrator,Linux账号是root,阿小云来详细说下阿里云服务器远程登录连接用户名和密码查询方法
10926 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
10324 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
11887 0
windows server 2008阿里云ECS服务器安全设置
最近我们Sinesafe安全公司在为客户使用阿里云ecs服务器做安全的过程中,发现服务器基础安全性都没有做。为了为站长们提供更加有效的安全基础解决方案,我们Sinesafe将对阿里云服务器win2008 系统进行基础安全部署实战过程! 比较重要的几部分 1.
8739 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
12176 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,云吞铺子总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系统盘、创建快照、配置安全组等操作如何登录ECS云服务器控制台? 1、先登录到阿里云ECS服务器控制台 2、点击顶部的“控制台” 3、通过左侧栏,切换到“云服务器ECS”即可,如下图所示 通过ECS控制台的远程连接来登录到云服务器 阿里云ECS云服务器自带远程连接功能,使用该功能可以登录到云服务器,简单且方便,如下图:点击“远程连接”,第一次连接会自动生成6位数字密码,输入密码即可登录到云服务器上。
21654 0
阿里云服务器ECS登录用户名是什么?系统不同默认账号也不同
阿里云服务器Windows系统默认用户名administrator,Linux镜像服务器用户名root
3668 0
+关注
markfork
简介:个人专注后端开发、在MySQL数据库、Java并发编程、有比较深入的学习,平时喜欢研究一些中间件的相关理论及实操、如Redis、Nginx。 愿景:打造个人知识ip 个人博客:markfork.com 个人简书:https://www.jianshu.com/u/c1
81
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载