S2SH框架搭建—基于注解配置
此次搭建s2sh框架为本人练手之用,如有不足请见谅,但希望能帮助到大家!
框架采用struts2.3.34、spring4.3.14、hibernate5.1.12版本搭建,jdk版本采用1.6。
框架中一些固定配置不需要长改动,此部分直接配置到xml中,其他配置则使用注解。
1、 S2SH框架介绍
Struts:控制层,用来控制的。
Spring:对Struts和Hibernate进行管理,整合的。
Hibernate:操控数据库,持久化操作。
框架优点:
1.spring管理对象的实例化,把对象的创建和获取放到外部,更加的灵活方便。
2.Hibernate避免了JDBC连接数据库的冗余繁杂。
3.各层分工明细,实现了各层之间的解耦,代码更加灵活
2、 框架依赖包下载
1) Spring
Spring版本所需JDK支持:
Spring Framework 3.x | JDK5+ |
Spring Framework 4.x | JDK6+ |
Spring Framework 5.x | JDK8+ |
2) struts2
下载地址:http://struts.apache.org/download.cgi
Struts2版本所需JDK支持:
Struts2.3.x及以下 | JDK5+ |
Struts2.5.x | JDK7+ |
3) hibernate
下载地址:http://hibernate.org/orm/releases/5.1/
Hibernate版本所需JDK支持:
Hibernate 5.0 | JDK 6+ |
Hibernate 5.1 | JDK 6+ |
Hibernate 5.2 | JDK 8+ |
Hibernate 5.3 | JDK 8+ |
4)其他所需jar可自行搜索下载
3、 项目总体结构
4、 导入框架所需jar包
5、 配置文件
1) web.xml,其中主要配置spring的listener、struts2的filter,用于启动加载spring、struts2.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>ssh-xml</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- spring的监听器配置开始 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 使Spring支持request与session的scope,如:<bean id="loginAction" class="com.foo.LoginAction" scope="request"/> -->
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<!-- Spring 刷新Introspector防止内存泄露 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<!-- 设置编码,防止表单提交的数据或者上传/下载中文名称文件出现乱码 -->
<filter>
<filter-name>encodingFilter</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>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<!-- 事务处理拦截器, 把一个Hibernate Session和一次完整的请求过程对应的线程相绑定。目的是为了实现"Open Session in View"的模式 -->
<!-- 它允许在事务提交之后延迟加载显示所需要的对象, 解决懒加载的问题,配置在Struts2过滤器之前 -->
<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>flushMode</param-name>
<param-value>AUTO</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>openSessionInView</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<!-- 配置Struts2 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
2) 属性文件jdbc.properties,配置数据源的相关信息。
### HIBERNATE CONFIG
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.format_sql=false
hibernate.show_sql=false
hibernate.fetch_size=20
hibernate.batch_size=10
hibernate.hbm2ddl=none
### C3P0 CONFIG(NOT BE USED)
jdbc.username=root
jdbc.password=root
jdbc.url=jdbc:mysql://localhost:3306/sshdemo?useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc.driver=com.mysql.jdbc.Driver
checkoutTimeout=30000
idleConnectionTestPeriod=60
initialPoolSize=5
maxIdleTime=10
maxPoolSize=20
minPoolSize=2
maxStatements=0
maxStatementsPerConnection=0
3) spring配置文件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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"
default-autowire="byName" default-lazy-init="false">
<!-- 所有配置类都使用注解,自动加载构建bean -->
<context:annotation-config />
<context:component-scan base-package="com.folwind" />
<!-- 加载属性文件 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<!--
C3P0数据源:
driverClass:数据库驱动;
jdbcUrl:数据库连接;
user:数据库用户名;
password:数据库用户密码;
(以上为必须配置的属性)
acquireIncrement:当连接池中的连接用完时,C3P0一次性创建新连接的数目,默认为3;
acquireRetryAttempts:定义在从数据库获取新连接失败后重复尝试获取的次数,默认为30;
acquireRetryDelay:两次连接中间隔时间,单位毫秒,默认为1000;
autoCommitOnClose:连接关闭时默认将所有未提交的操作回滚。默认为false;
automaticTestTable: C3P0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数,那么属性preferredTestQuery将被忽略。
你不能在这张Test表上进行任何操作,它将中为C3P0测试所用,默认为null;
breakAfterAcquireFailure:获取连接失败将会引起所有等待获取连接的线程抛出异常。但是数据源仍有效保留,并在下次调用getConnection()的时候继续尝试获取连接。
如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。默认为 false;
checkoutTimeout:当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出SQLException,如设为0则无限期等待。单位毫秒,默认为0;
connectionTesterClassName: 通过实现ConnectionTester或QueryConnectionTester的类来测试连接,类名需设置为全限定名。默认为 com.mchange.v2.C3P0.impl.DefaultConnectionTester;
idleConnectionTestPeriod:隔多少秒检查所有连接池中的空闲连接,默认为0表示不检查;
initialPoolSize:初始化时创建的连接数,应在minPoolSize与maxPoolSize之间取值。默认为3;
maxIdleTime:最大空闲时间,超过空闲时间的连接将被丢弃。为0或负数则永不丢弃。默认为0;
maxPoolSize:连接池中保留的最大连接数。默认为15;
minPoolSize:连接池中保留的最小连接数
maxStatements:JDBC的标准参数,用以控制数据源内加载的PreparedStatement数量。但由于预缓存的Statement属于单个Connection而不是整个连接池。
所以设置这个参数需要考虑到多方面的因素,如果maxStatements与 maxStatementsPerConnection均为0,则缓存被关闭。默认为0;
maxStatementsPerConnection:连接池内单个连接所拥有的最大缓存Statement数。默认为0;
numHelperThreads:C3P0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能,通过多线程实现多个操作同时被执行。默认为3;
preferredTestQuery:定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个参数能显著提高测试速度。测试的表必须在初始数据源的时候就存在。默认为null;
propertyCycle: 用户修改系统配置参数执行前最多等待的秒数。默认为300;
testConnectionOnCheckout:因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的时候都 将校验其有效性。
建议使用idleConnectionTestPeriod或automaticTestTable等方法来提升连接测试的性能。默认为false;
testConnectionOnCheckin:如果设为true那么在取得连接的同时将校验连接的有效性。默认为false
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="driverClass" value="${jdbc.driver}" />
<property name="checkoutTimeout" value="${checkoutTimeout}" />
<property name="idleConnectionTestPeriod" value="${idleConnectionTestPeriod}" />
<property name="initialPoolSize" value="${initialPoolSize}" />
<property name="maxIdleTime" value="${maxIdleTime}" />
<property name="maxPoolSize" value="${maxPoolSize}" />
<property name="minPoolSize" value="${minPoolSize}" />
<property name="maxStatements" value="${maxStatements}" />
<property name="maxStatementsPerConnection" value="${maxStatementsPerConnection}" />
</bean>
<!-- 使用Hiberanate 创建sessionfactory
在hibernate5中获取sessionFactory ,
hibernate3则class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
hibernate4则class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
设置属性说明:
hibernate.dialect:设置方言
hibernate.format_sql:输出格式化的sql
hibernate.show_sql:控制台输出sql
hibernate.jdbc.fetch_size:Hibernate每次从数据库中取出并放到JDBC的Statement中的记录条数。FetchSize设的越大,读数据库的次数越少,速度越快,Fetch Size越小,读数据库的次数越多,速度越慢
hibernate.jdbc.batch_size:Hibernate批量插入,删除和更新时每次操作的记录数。BatchSize越大,批量操作的向数据库发送Sql的次数越少,速度就越快,同样耗用内存就越大
hibernate.hbm2ddl.auto:自动创建|更新|验证数据库表结构。有以下几个参数:
create:每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
create-drop:每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了
但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
validate :每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
current_session_context_class:使用缓存机制,配置此处 sessionFactory.getCurrentSession()可以完成一系列的工作,当调用时,hibernate将session绑定到当前线程,
事务结束后,hibernate将session从当前线程中释放,并且关闭session。当再次调用getCurrentSession()时,将得到一个新的session,并重新开始这一系列工作。
(hibernate3:Thread或jta);(hibernate4:org.springframework.orm.hibernate4.SpringSessionContext);
(hibernate5:org.springframework.orm.hibernate5.SpringSessionContext)
hibernate.cache.use_second_level_cache:是否启用二级缓存,true或false
hibernate.cache.provider_class:使用Ehcache缓存;hibernate3是org.hibernate.cache.HashtableCacheProvider;hibernate4是net.sf.ehcache.hibernate.EhCacheProvider
hibernate.cache.use_query_cache:是否启用查询缓存,true或false
hibernate.temp.use_jdbc_metadata_defaults:Hibernate默认是使用jdbc方式来取的,若使用连接池的方式,将此配置项置为false,否则启动时抛出异常Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.Invocation
-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.jdbc.fetch_size">${hibernate.fetch_size}</prop>
<prop key="hibernate.jdbc.batch_size">${hibernate.batch_size}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl}</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
</props>
</property>
<!--自动扫描(实体类)注解包:实体类位置为:com.spring.mvc.entities.User,不能写成:com.spring.mvc.entities,而要写成:com.spring.mvc,packagesToScan要比实际上前一层-->
<property name="packagesToScan">
<list>
<value>com.folwind.**.entity</value>
</list>
</property>
</bean>
<!--hibernate3.1以及以上版本取消了hibernateTemplate,hibernate4需要通过getCurrentSession()获取session -->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 加载事务管理驱动 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 配置事务切面 -->
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="do*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="handle*" propagation="REQUIRED" />
<tx:method name="excute*" propagation="REQUIRED" />
<tx:method name="analysis*" propagation="REQUIRED" />
<tx:method name="receive*" propagation="REQUIRED" />
<tx:method name="search*" propagation="REQUIRED" read-only="true"/>
<tx:method name="find*" propagation="REQUIRED" read-only="true"/>
<tx:method name="load*" propagation="REQUIRED" read-only="true"/>
<tx:method name="get*" propagation="REQUIRED" read-only="true"/>
<tx:method name="*" propagation="REQUIRED" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="(execution(* com.folwind..service.*.*(..))) or (execution(* com.folwind.framework.core.BaseService.*(..)))" id="txPoint" />
<aop:advisor advice-ref="transactionAdvice" pointcut-ref="txPoint" />
</aop:config>
</beans>
4) struts2配置文件struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!-- 基础配置 -->
<!-- CONSTANT CONFIG -->
<constant name="struts.locale" value="zh_CN"/>
<constant name="struts.i18n.encoding" value="UTF-8"/>
<constant name="struts.multipart.parser" value="jakarta"/>
<constant name="struts.multipart.saveDir" value=""/>
<constant name="struts.multipart.maxSize" value="41943040"/>
<constant name="struts.ui.templateDir" value="template" />
<!-- 不用dojo的及struts2复杂标签样式的就把主题设置为simple,这样可以不加载多余的模板 -->
<constant name="struts.ui.theme" value="simple"/>
<!-- 自动动态方法的调用,使用这个设置后可以这样调用:action!method -->
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<!-- 把它设置为开发模式,发布时要设置为false -->
<constant name="struts.devMode" value="true" />
<!-- 设置在class被修改时是否热加载,发布时要设置为false -->
<constant name="struts.convention.classes.reload" value="true"/>
<!-- 该属性设置是否每次HTTP请求到达时,系统都重新加载资源文件,该属性默认值是false -->
<constant name="struts.i18n.reload" value="false" />
<!-- 当struts 2的配置文件修改后,系统是否自动重新加载该文件,默认值为false -->
<constant name="struts.configuration.xml.reload" value="true"></constant>
<!-- 指定Struts2默认的ObjectFactoryBean,该属性默认值是spring -->
<constant name="struts.objectFactory" value="spring"></constant>
<!-- 在struts2中设置处理请求的后缀为 -->
<constant name="struts.action.extension" value="do" />
<!-- 该属性设置Struts 2是否允许在Action名中使用斜线,该属性的默认值是false -->
<!-- <constant name="struts.enable.SlashesInActionNames" value="true"/> -->
<!-- 指定jsp文件所在的目录地址,默认为/WEB-INF/content/ -->
<constant name="struts.convention.result.path" value="" />
<!-- 一个action名字的获取。比如为HelloWorldAction。按照配置,actionName为hello_world。 -->
<constant name="struts.convention.action.suffix" value="Action"/>
<constant name="struts.convention.action.name.lowercase" value="true"/>
<constant name="struts.convention.action.name.separator" value="-"/>
<!-- 是否不扫描类。一定要设为false,否则convention插件不起作用,零配置也没有意义。 -->
<constant name="struts.convention.action.disableScanning" value="false"/>
<!-- 设置默认的父包,一般我们都设置一个default包继承自struts-default。大部分类再继承default。如果有特殊的类需要特殊的包,只能在action中再指定父包了。 -->
<constant name="struts.convention.default.parent.package" value="app-default"/>
<!-- 确定搜索包的路径。只要是结尾为action的包都要搜索。basePackage按照默认不用配置,如果配置,只会找以此配置开头的包。locators及locators.basePackage都是一组以逗号分割的字符串 -->
<constant name="struts.convention.package.locators" value="action"/>
<constant name="struts.convention.package.locators.disable" value="false"/>
<constant name="struts.convention.package.locators.basePackage" value="com.folwind"/>
<constant name="struts.objectFactory.spring.autoWire" value="name"/>
<package name="app-default" namespace="/" extends="struts-default, json-default">
<!-- INTERCEPTORS CONFIG -->
<interceptors>
<interceptor-stack name="appDefaultStack">
<interceptor-ref name="logger" />
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="datetime"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="paramNameMaxLength">1000</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="debugging"/>
<interceptor-ref name="deprecation"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="appDefaultStack" />
<!-- GLOBAL RESULT AND GLOBAL EXCEPTION CONFIG -->
<global-results>
<result name="json" type="json" >
<!-- 这里指定将被Struts2序列化的属性,该属性在action中必须有对应的getter方法 -->
<!-- 代表从哪里开始序列化 -->
<param name="root">json</param>
<!-- <param name="ignoreHierarchy">false</param> -->
<!-- 代表排除Action中的哪些属性,排除多个属性时,使用逗号进行分隔(即不需要序列化的属性) -->
<!-- <param name="excludeProperties">age</param> -->
<!-- 代表包含Action中的哪些属性,包含多个属性是,使用逗号进行分隔(即需要序列化的属性) -->
<!-- <param name="includeProperties">address</param> -->
<!-- 代表排除Action中属性值为空的字段, 使用true/false 默认为false(即包含属性值为null的字段) -->
<param name="excludeNullProperties">true</param>
<!-- 指定内容类型,默认为application/json,IE浏览器会提示下载 -->
<!-- <param name="contentType">text/html</param> -->
<!-- 注意:如果相同属性同时定义了excludeProperties和includeProperties,
那么excludeProperties的优先级要高,因此不对该属性进行序列化 -->
<!--
private String defaultEncoding = "ISO-8859-1";//默认的编码
private List<Pattern> includeProperties;//被包含的属性的正则表达式,这些属性的值将被序列化为JSON字符串,传送到客户端
private List<Pattern> excludeProperties;//被排除的属性的正则表达式,这些属性的值在对象序列化时将被忽略
private String root;//根对象,即要被序列化的对象,如不指定,将序列化action中所有可被序列化的数据
private boolean wrapWithComments;//是否包装成注释
private boolean prefix;//前缀
private boolean enableGZIP = false;//是否压缩
private boolean ignoreHierarchy = true;//是否忽略层次关系,即是否序列化对象父类中的属性
private boolean ignoreInterfaces = true;//是否忽略接口
private boolean enumAsBean = false;//是否将枚举类型作为一个bean处理
private boolean excludeNullProperties = false;//是否排除空的属性,即是否不序列化空值属性
private int statusCode;//HTTP状态码
private int errorCode;//HTTP错误码
private String contentType;//内容类型,通常为application/json,在IE浏览器中会提示下载,可以通过参数配置<param name="contentType">text/html</param>,则不提示下载
private String wrapPrefix;//包装前缀
private String wrapSuffix;//包装后缀
-->
</result>
<result name="login">/index.jsp</result>
<result name="exception">/framework/common/exception.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="java.lang.Exception" result="exception"/>
</global-exception-mappings>
</package>
</struts>
5) 日志配置log4j.properties,配置日志打印的相关信息
#日志框架
#日志等级
#TRACE:详细等级,堆栈信息
#debug:类似于System.out.print
#info:类似于Hibernate的show_sql
#warn:不影响运行, 只是提示
#error:出现异常
#全局日志等级配置,输出位置
log4j.rootLogger=info,stdout,R
#stdout控制器
#org.apache.log4j.ConsoleAppender(控制台),
#org.apache.log4j.FileAppender(文件),
#org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
#org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
#org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
#org.apache.log4j.net.SMTPAppender(邮件发送日志)
#org.apache.log4j.jdbc.JDBCAppender 输出到数据库
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
#org.apache.log4j.HTMLLayout(以HTML表格形式布局),
#org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
#org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
#org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
#输出格式
# %c 列出logger名字空间的全称,如果加上{<层数>}表示列出从最内层算起的指定层数的名字空间
# 假设当前logger名字空间是"a.b.c"
# %c a.b.c
# %c{2} b.c
# %20c (若名字空间长度小于20,则左边用空格填充)
# %-20c (若名字空间长度小于20,则右边用空格填充)
# %.30c (若名字空间长度超过30,截去多余字符)
# %20.30c (若名字空间长度小于20,则左边用空格填充;若名字空间长度超过30,截去多余字符)
# %-20.30c (若名字空间长度小于20,则右边用空格填充;若名字空间长度超过30,截去多余字符)
# %C 列出调用logger的类的全名(包含包路径)
# 假设当前类是"org.apache.xyz.SomeClass"
# %C org.apache.xyz.SomeClass
# %C{1} SomeClass
# %d 显示日志记录时间,{<日期格式>}使用ISO8601定义的日期格式
# %d{yyyy/MM/dd HH:mm:ss,SSS} 2005/10/12 22:23:30,117
# %d{ABSOLUTE} 22:23:30,117
# %d{DATE} 12 Oct 2005 22:23:30,117
# %d{ISO8601} 2005-10-12 22:23:30,117
# %F 显示调用logger的源文件名
# %F MyClass.java
# %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数
# %l MyClass.main(MyClass.java:129)
# %L 显示调用logger的代码行
# %L 129
# %m 显示输出消息
# %m This is a message for debug.
# %M 显示调用logger的方法名
# %M main
# %n 当前平台下的换行符
# %n Windows平台下表示rn,UNIX平台下表示n
# %p 显示该条日志的优先级
# %p INFO
# %r 显示从程序启动时到记录该条日志时已经经过的毫秒数
# %r 1215
# %t 输出产生该日志事件的线程名
# %t MyClass
# %x 按NDC(Nested Diagnostic Context,线程堆栈)顺序输出日志
# 假设某程序调用顺序是MyApp调用com.foo.Bar
# %c %x - %m%n MyApp - Call com.foo.Bar.
# com.foo.Bar - Log in Bar
# MyApp - Return to MyApp.
# %X 按MDC(Mapped Diagnostic Context,线程映射表)输出日志。通常用于多个客户端连接同一台服务器,方便服务器区分是那个客户端访问留下来的日志。
# %X{5} (记录代号为5的客户端的日志)
# %% 显示一个百分号
# %% %
log4j.appender.stdout.layout.ConversionPattern= [%p] %d{yyyy-MM-dd HH:mm:ss,SSS} [%c.%M(%F:%L)] --> %m%n
#log4j.appender.stdout.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
#文件路径输出
log4j.appender.R=org.apache.log4j.RollingFileAppender
#默认输出到tomcat的根路径或者运行测试工程的根路径
log4j.appender.R.File=D\:/work/workspaces/training-workspaces/apache-tomcat-6.0.37/logs/ssh-scan.log
log4j.appender.D.Append = true
#log4j.appender.D.Threshold = error
log4j.appender.R.MaxFileSize=1024KB
# Keep three backup files.
log4j.appender.R.MaxBackupIndex=20
# Pattern to output: date priority [category] - message
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern= [%p] %d{yyyy-MM-dd HH:mm:ss,SSS} [%c.%M(%F:%L)] --> %m%n
6、 Base组件定义,定义分页组件PageModel、BaseDAO持久化操作、BaseService基本业务逻辑操作、BaseActionSupport控制层
1) 分页组件PageModel
package com.folwind.framework.core;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class PageModel {
// 总记录数
private int totalRecords = 0;
// 结果集
private List<?> data = Collections.emptyList();
// 当前页
private int pageNo = 1;
// 每页显示多少条
private int pageSize = 10;
private List<String> sortField = null;
private List<String> directions = null;
private boolean success = true;
private String msg = "";
private final String SPACE = " ";
public int getTotalRecords() {
return totalRecords;
}
public void setTotalRecords(int totalRecords) {
this.totalRecords = totalRecords;
}
public List<?> getData() {
return data;
}
public void setData(List<?> data) {
this.data = data;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
public boolean isNull() {
if (data == null || data.size() <= 0) {
return true;
} else {
return false;
}
}
public void addSort(String fieldName, String direction) {
if(this.sortField == null) {
this.sortField = new ArrayList<String>(1);
this.directions = new ArrayList<String>(1);
}
this.sortField.add(fieldName);
this.directions.add(direction);
}
public String generateSortStr() {
StringBuilder builder = new StringBuilder();
if(this.sortField != null) {
int length = this.sortField.size();
for (int i = 0; i < length; i++) {
if( i > 0) {
builder.append(", ");
}
builder.append(this.sortField.get(i));
builder.append(SPACE);
builder.append(this.directions.get(i));
}
}
return builder.toString();
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
2) BaseDAO
package com.folwind.framework.core;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.springframework.orm.hibernate5.HibernateCallback;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;
import com.folwind.framework.util.HqlConvertUtil;
import com.folwind.framework.util.PageUtil;
@SuppressWarnings("unchecked")
@Repository
public class BaseDAO<T> extends HibernateDaoSupport {
public T load(Class<T> clazz, Serializable id) {
return this.getHibernateTemplate().load(clazz, id);
}
public void save(T obj) throws Exception {
getHibernateTemplate().save(obj);
getHibernateTemplate().flush();
}
public void update(T obj) throws Exception {
getHibernateTemplate().update(obj);
getHibernateTemplate().flush();
}
public void saveOrUpdate(T obj) throws Exception {
getHibernateTemplate().saveOrUpdate(obj);
getHibernateTemplate().flush();
}
public void merge(T obj) throws Exception {
getHibernateTemplate().merge(obj);
getHibernateTemplate().flush();
}
public void delete(T obj) throws Exception {
if(obj != null) {
getHibernateTemplate().delete(obj);
getHibernateTemplate().flush();
}
}
public void delete(Class<T> clazz, Serializable id) throws Exception {
T obj = load(clazz, id);
if (obj != null)
delete(obj);
}
public void delete(String hql) throws Exception {
this.getHibernateTemplate().deleteAll(find(hql));
}
public void delete(String hql, String paramName, Object value) throws Exception {
this.getHibernateTemplate().deleteAll(find(hql, paramName, value));
}
public void delete(String hql, List<String> paramNames, List<Object> values) throws Exception {
this.getHibernateTemplate().deleteAll(find(hql, paramNames, values));
}
public List<T> findAll(Class<T> clazz) throws Exception {
return this.getHibernateTemplate().loadAll(clazz);
}
public List<T> find(String hql) throws Exception {
return (List<T>) getHibernateTemplate().find(HqlConvertUtil.convert(hql));
}
public List<T> find(String hql, String paramName, Object value) throws Exception {
return (List<T>) getHibernateTemplate().findByNamedParam(HqlConvertUtil.convert(hql), paramName, value);
}
public List<T> find(String hql, List<String> paramNames, List<Object> values) throws Exception {
return (List<T>) getHibernateTemplate().findByNamedParam(HqlConvertUtil.convert(hql), paramNames.toArray(new String[paramNames.size()]), values.toArray());
}
/**
* 根据属性名和属性值查询对象 ,返回唯一对象
*/
public T findBy(Class<T> clazz, String paramName, Object value) throws Exception {
Criteria criteria = currentSession().createCriteria(clazz);
criteria.add(Restrictions.eq(paramName, value));
return (T) criteria.uniqueResult();
}
/**
* 根据属性名和属性值查询对象 ,返回符合条件的对象列表
*/
public List<T> findAllBy(Class<T> clazz, String paramName, Object value) throws Exception {
Criteria criteria = currentSession().createCriteria(clazz);
criteria.add(Restrictions.eq(paramName, value));
return criteria.list();
}
/**
* 根据属性名和属性值查询对象 ,返回符合条件的排序对象列表
*/
public List<T> findAllBy(Class<T> clazz, String paramName, Object value, String orderby) throws Exception {
Criteria criteria = currentSession().createCriteria(clazz);
criteria.add(Restrictions.eq(paramName, value));
criteria.addOrder(Order.asc(orderby));
return criteria.list();
}
public List<T> findAllBy(Class<T> clazz, String paramName, Object value, String orderby, boolean asc) throws Exception {
Criteria criteria = currentSession().createCriteria(clazz);
criteria.add(Restrictions.eq(paramName, value));
if (asc)
criteria.addOrder(Order.asc(orderby));
else
criteria.addOrder(Order.desc(orderby));
return criteria.list();
}
/**
* 根据属性名和属性值查询对象 ,返回符合条件的对象列表
*/
public List<T> findAllByLike(Class<T> clazz, String name, Object value) throws Exception {
Criteria criteria = currentSession().createCriteria(clazz);
criteria.add(Restrictions.like(name, value));
return criteria.list();
}
/**
* -----------------------------------------------------------------------
* 搜索统一实现
* -----------------------------------------------------------------------
*/
public PageModel findPage(String hql, PageModel pm) throws Exception {
return findPage(hql, null, null, pm);
}
/**
* 根据HQL语句进行分页查询
*
* @param hql HQL语句
* @param params HQL语句带的多个参数值
* @param offset 从第几条记录开始查询
* @param pageSize 每页显示多少行
* @return 分页模型
*/
public PageModel findPage(final String hql, final List<String> paramNames, final List<Object> values, PageModel pm) throws Exception {
// 获取总记录数total
if(paramNames != null && values != null && paramNames.size() != values.size()) {
throw new Exception("参数列表不一致!");
}
final String convertedHql = HqlConvertUtil.convert(hql);
final String countHql = getCountHql(convertedHql);
int total = (Integer)getHibernateTemplate().execute(new HibernateCallback<Object>() {
public Object doInHibernate(Session session) throws HibernateException {
Query query = session.createQuery(countHql);
setParameters(query, paramNames, values);
return ((Long) query.uniqueResult()).intValue();
}
});
final int pageNo = pm.getPageNo();
final int pageSize = pm.getPageSize();
List<?> datas = (List<?>)getHibernateTemplate().execute(new HibernateCallback<Object>() {
public Object doInHibernate(Session session) throws HibernateException {
Query query = session.createQuery(convertedHql);
setParameters(query, paramNames, values);
return query.setFirstResult((pageNo - 1) * pageSize).setMaxResults(pageSize).list();
}
});
int pageCurrent = PageUtil.getCurrentPage(total, pm.getPageSize(), pm.getPageNo());
pm.setPageNo(pageCurrent);
// 返回数据
pm.setTotalRecords(total);
pm.setData(datas);
return pm;
}
public int executeSql(String sql) throws Exception {
Query query = currentSession().createSQLQuery(sql);
return query.executeUpdate();
}
public List<Map<String, Object>> findBySql(String sql) throws Exception {
Query query = currentSession().createSQLQuery(sql);
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return query.list();
}
public List<Map<String, Object>> findBySql(String sql, String paramName, Object value) throws Exception {
Query query = currentSession().createSQLQuery(sql);
query.setParameter(paramName, value);
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return query.list();
}
public List<Map<String, Object>> findBySql(String sql, List<String> paramNames, List<Object> values) throws Exception {
Query query = currentSession().createSQLQuery(sql);
setParameters(query, paramNames, values);
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return query.list();
}
public PageModel findPageBySql(String sql, String countSql, PageModel pm) throws Exception {
Query countquery = currentSession().createSQLQuery(countSql);
List<?> countList = countquery.list();
int rowCount = 0;
if ((countList != null) && (!countList.isEmpty())) {
rowCount = new Integer(countList.get(0).toString()).intValue();
}
int pageCurrent = PageUtil.getCurrentPage(rowCount, pm.getPageSize(), pm.getPageNo());
pm.setTotalRecords(rowCount);
pm.setPageNo(pageCurrent);
Query query = currentSession().createSQLQuery(sql);
query.setFirstResult((pageCurrent - 1) * pm.getPageSize());
query.setMaxResults(pm.getPageSize());
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
pm.setData(query.list());
return pm;
}
public PageModel findPageBySql(String sql, String countSql, String paramName, Object value, PageModel pm) throws Exception {
Query countquery = currentSession().createSQLQuery(countSql);
countquery.setParameter(paramName, value);
List<?> countList = countquery.list();
int rowCount = 0;
if ((countList != null) && (!countList.isEmpty())) {
rowCount = new Integer(countList.get(0).toString()).intValue();
}
int pageCurrent = PageUtil.getCurrentPage(rowCount, pm.getPageSize(), pm.getPageNo());
pm.setTotalRecords(rowCount);
pm.setPageNo(pageCurrent);
Query query = currentSession().createSQLQuery(sql);
query.setParameter(paramName, value);
query.setFirstResult((pageCurrent - 1) * pm.getPageSize());
query.setMaxResults(pm.getPageSize());
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
pm.setData(query.list());
return pm;
}
public PageModel findPageBySql(String sql, String countSql, List<String> paramNames, List<Object> values, PageModel pm) throws Exception {
Query countquery = currentSession().createSQLQuery(countSql);
setParameters(countquery, paramNames, values);
List<?> countList = countquery.list();
int rowCount = 0;
if ((countList != null) && (!countList.isEmpty())) {
rowCount = new Integer(countList.get(0).toString()).intValue();
}
int pageCurrent = PageUtil.getCurrentPage(rowCount, pm.getPageSize(), pm.getPageNo());
pm.setTotalRecords(rowCount);
pm.setPageNo(pageCurrent);
Query query = currentSession().createSQLQuery(sql);
setParameters(query, paramNames, values);
query.setFirstResult((pageCurrent - 1) * pm.getPageSize());
query.setMaxResults(pm.getPageSize());
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
pm.setData(query.list());
return pm;
}
/**
* 根据HQL语句,获得查找总记录数的HQL语句 如: select ... from Orgnization o where o.parent is
* null 经过转换,可以得到: select count(*) from Orgnization o where o.parent is null
* @param hql
* @return
*/
private String getCountHql(String hql) throws Exception {
int index = hql.indexOf("from");
if (index != -1) {
return "select count(*) " + hql.substring(index);
}
return null;
}
private void setParameters(Query query, List<String> paramNames, List<Object> values) throws HibernateException {
if (paramNames != null && paramNames.size() > 0) {
int length = paramNames.size();
Object obj = null;
for (int i = 0; i < length; i++) {
obj = values.get(i);
if(obj == null) {
continue;
}
if(Collection.class.isAssignableFrom(obj.getClass())) {
query.setParameterList(paramNames.get(i), (Collection<?>) obj);
}
else if(obj.getClass().isArray()) {
query.setParameterList(paramNames.get(i), (Object[])obj);
}
else {
query.setParameter(paramNames.get(i), values.get(i));
}
}
}
}
}
3) BaseService
package com.folwind.framework.core;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
public abstract class BaseService<T> {
@Autowired
protected BaseDAO<T> dao;
public abstract Class<T> getEntityClass();
public abstract String getEntityClassName();
/**
* 生成hql的条件语句,开头为and条件连接符,实体别名为t
* @param queryEntity 存储查询条件的实体对象
* @param paramNames 条件语句中的插值符
* @param values 条件语句中插值符的值
* @return
*/
protected abstract String generateWheres(T queryEntity, List<String> paramNames, List<Object> values) throws Exception;
public T loadById(Serializable id) {
return dao.load(getEntityClass(), id);
}
public void save(T obj) throws Exception {
dao.save(obj);
}
public void update(T obj) throws Exception {
dao.update(obj);
}
public void saveOrUpdate(T obj) throws Exception {
dao.saveOrUpdate(obj);
}
public void merge(T obj) throws Exception {
dao.merge(obj);
}
public void delete(T obj) throws Exception {
dao.delete(obj);
}
public void deleteById(Serializable id) throws Exception {
dao.delete(getEntityClass(), id);
}
public void deleteByIds(Serializable[] ids) throws Exception {
for (int i = 0; i < ids.length; i++) {
dao.delete(getEntityClass(), ids[i]);
}
}
public List<T> findAll() throws Exception {
return dao.findAll(getEntityClass());
}
/**
* 根据属性名和属性值查询对象 ,返回唯一对象
*/
public T findBy(String name, Object value) throws Exception {
return dao.findBy(getEntityClass(), name, value);
}
/**
* 根据属性名和属性值查询对象 ,返回符合条件的对象列表
*/
public List<T> findAllBy(String name, Object value) throws Exception {
return dao.findAllBy(getEntityClass(), name, value);
}
/**
* 根据属性名和属性值查询对象 ,返回符合条件的排序对象列表
*/
public List<T> findAllBy(String name, Object value, String orderby) throws Exception {
return dao.findAllBy(getEntityClass(), name, value, orderby);
}
public List<T> findAllBy(String name, Object value, String orderby, boolean asc) throws Exception {
return dao.findAllBy(getEntityClass(), name, value, orderby, asc);
}
/**
* 根据属性名和属性值查询对象 ,返回符合条件的对象列表
*/
public List<T> findAllByLike(String name, Object value) throws Exception{
return dao.findAllByLike(getEntityClass(), name, value);
}
/**
* -----------------------------------------------------------------------
* 搜索统一实现
* -----------------------------------------------------------------------
*/
protected PageModel findPage(String hql, PageModel pm) throws Exception{
return dao.findPage(hql, pm);
}
/**
* 根据HQL语句进行分页查询
*
* @param hql HQL语句
* @param params HQL语句带的多个参数值
* @param offset 从第几条记录开始查询
* @param pageSize 每页显示多少行
* @return 分页模型
*/
protected PageModel findPage(String hql, List<String> paramNames, List<Object> values, PageModel pm) throws Exception {
return dao.findPage(hql, paramNames, values, pm);
}
public PageModel findPage(T queryEntity, PageModel pm) throws Exception {
List<String> paramNames = new ArrayList<String>();
List<Object> values = new ArrayList<Object>();
StringBuilder builder = generateHql(generateWheres(queryEntity, paramNames, values), pm.generateSortStr());
return dao.findPage(builder.toString(), paramNames, values, pm);
}
public BaseDAO<T> getDao() {
return dao;
}
public void setDao(BaseDAO<T> dao) {
this.dao = dao;
}
/**
* 生成hql语句,实体别名为t
* @param wheres 条件语句,开头为and条件连接符
* @param orderBy 排序语句,可多个字段排序,例:field1 asc,field2 desc
* @return
*/
protected StringBuilder generateHql(String wheres, String orderBy) throws Exception {
StringBuilder builder = new StringBuilder();
builder.append("from ");
builder.append(getEntityClassName());
builder.append(" t ");
builder.append(" where 1=1 ");
if(StringUtils.isNotBlank(wheres)) {
builder.append(wheres);
}
if(StringUtils.isNotBlank(orderBy)) {
builder.append(" order by ");
builder.append(orderBy);
}
return builder;
}
}
4) BaseActionSupport
package com.folwind.framework.core;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONArray;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;
import org.springframework.beans.factory.annotation.Autowired;
import com.folwind.sys.menu.service.SysMenuService;
import com.folwind.sys.user.service.SysUserService;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;
//继承ActionSupport,让本类具备强大的功能(例如:校验、国际化等)
public abstract class BaseActionSupport extends ActionSupport implements SessionAware, ServletRequestAware, ServletResponseAware, Preparable {
/**
*
*/
private static final long serialVersionUID = 1L;
protected final String JSON = "json";
protected HttpServletResponse response;
protected HttpServletRequest request;
protected Map<String, Object> session;
private Object json;
private Map<String, Object> jsonMap;
//=================Service注入========================
@Autowired
protected SysUserService sysUserService;
@Autowired
protected SysMenuService sysMenuService;
@Override
public void prepare() throws Exception {
this.jsonMap = new HashMap<String, Object>(5);
setSuccessJson();
}
@Override
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
@Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
public void setJson(Object json) {
this.json = json;
}
public Object getJson() {
return this.json;
}
protected void setSuccessJson() {
jsonMap.put("success", Boolean.TRUE);
jsonMap.put("msg", "操作成功");
setJson(jsonMap);
}
protected void setSuccessJson(String msg) {
jsonMap.put("success", Boolean.TRUE);
jsonMap.put("msg", msg);
setJson(jsonMap);
}
protected void addJson(String key, Object value) {
jsonMap.put(key, value);
setJson(jsonMap);
}
protected void setFailJson(String errorMsg) {
jsonMap.put("success", Boolean.FALSE);
jsonMap.put("msg", errorMsg);
setJson(jsonMap);
}
/**
* 将list转换成json数据
* @param list
* @return
*/
public String convertListToJson(List<?> list) {
//将list转为json
JSONArray jsonArray = new JSONArray();
jsonArray = JSONArray.fromObject(list);
return jsonArray.toString();
}
/**
* 输出字符串 Json数据
* @param json
*/
public void outPutJson(String json) {
try {
// 设置文本流头信息
response.setContentType("text/html;charset=UTF-8");
// 获取流
PrintWriter out = response.getWriter();
// 将流打到客户端
out.print(json);
// 清空缓存
out.flush();
// 关闭流
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
7、 Entity,数据库表ORM映射信息
package com.folwind.sys.user.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
/**
* SysUser entity. @author MyEclipse Persistence Tools
*/
@Entity//声明当前类为hibernate映射到数据库中的实体类
@Table(name = "T_SYS_USER")
public class SysUser implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
// Fields
@Id//声明此列为主键,作为映射对象的标识符
/**
* @GeneratedValue注解来定义生成策略
* GenerationType.TABLES 当前主键的值单独保存到一个数据库的表中
* GenerationType.SEQUENCE 利用底层数据库提供的序列生成标识符
* GenerationType.IDENTITY 采取数据库的自增策略
* GenerationType.AUTO 根据不同数据库自动选择合适的id生成方案,这里使用mysql,为递增型
*/
//@GeneratedValue(strategy = GenerationType.AUTO)
@GenericGenerator(name = "assigned", strategy = "assigned")
@GeneratedValue(generator="assigned")
@Column(name = "ID", unique=true, nullable = false, length=50)
private String id;
@Column(name = "PASSWORD", length = 32)
private String password;
@Column(name = "REAL_NAME", length = 255)
private String realName;
@Column(name = "EMAIL", length = 255)
private String email;
@Column(name = "MOBILE", length = 16)
private String mobile;
@Column(name = "ORG_ID", length = 50)
private String orgId;
// Constructors
/** default constructor */
public SysUser() {
}
/** minimal constructor */
public SysUser(String id) {
this.id = id;
}
/** full constructor */
public SysUser(String id, String password, String realName, String email,
String mobile, String orgId) {
this.id = id;
this.password = password;
this.realName = realName;
this.email = email;
this.mobile = mobile;
this.orgId = orgId;
}
// Property accessors
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRealName() {
return this.realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMobile() {
return this.mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getOrgId() {
return this.orgId;
}
public void setOrgId(String orgId) {
this.orgId = orgId;
}
}
8、 Service,service层业务逻辑操作,继承BaseService
package com.folwind.sys.user.service;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import com.folwind.framework.core.BaseService;
import com.folwind.sys.user.entity.SysUser;
@Service
public class SysUserService extends BaseService<SysUser> {
@Override
public Class<SysUser> getEntityClass() {
return SysUser.class;
}
@Override
public String getEntityClassName() {
return "SysUser";
}
@Override
protected String generateWheres(SysUser queryEntity,
List<String> paramNames, List<Object> values) throws Exception {
if(queryEntity == null) {
return "";
}
StringBuilder sb = new StringBuilder();
if(StringUtils.isNotBlank(queryEntity.getRealName())) {
sb.append(" and t.realName like :realName");
paramNames.add("realName");
values.add("%" + queryEntity.getRealName() + "%");
}
if(StringUtils.isNotBlank(queryEntity.getMobile())) {
sb.append(" and t.mobile like :mobile");
paramNames.add("mobile");
values.add("%" + queryEntity.getMobile() + "%");
}
return sb.toString();
}
}
9、 Action,action层控制逻辑操作,继承BaseActionSupport
package com.folwind.sys.user.action;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import com.folwind.framework.core.BaseActionSupport;
import com.folwind.framework.core.PageModel;
import com.folwind.framework.util.BeanUtil;
import com.folwind.framework.util.PageUtil;
import com.folwind.sys.user.entity.SysUser;
@Results({
@Result(name="list",location="/sys/user/jsp/user.jsp")
})
public class SysUserAction extends BaseActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
private final Log LOG = LogFactory.getLog(SysUserAction.class);
private SysUser entity;
private String id;
public String list() {
return "list";
}
public String search() {
PageModel pm = null;
try {
pm = PageUtil.createPageModel(request);
pm = sysUserService.findPage(getEntity(), pm);
pm.setSuccess(Boolean.TRUE);
pm.setMsg("查询数据成功!");
} catch (Exception e) {
if(pm == null) {
pm = new PageModel();
}
pm.setSuccess(Boolean.FALSE);
pm.setMsg("查询数据失败!");
LOG.error("查询数据失败!" + e.getMessage(), e);
}
setJson(pm);
return JSON;
}
public String searchById() {
try {
entity = sysUserService.loadById(id);
addJson("entity", entity);
setSuccessJson("查询数据成功!");
} catch (Exception e) {
setFailJson("查询数据失败!");
LOG.error("查询数据失败!" + e.getMessage(), e);
}
return JSON;
}
public String doCreate() {
try {
sysUserService.save(getEntity());
setSuccessJson("创建数据成功!");
} catch (Exception e) {
setFailJson("创建数据失败!");
LOG.error("创建数据失败!" + e.getMessage(), e);
}
return JSON;
}
public String doModify() {
try {
SysUser entity = getEntity();
SysUser oldEntity = sysUserService.loadById(entity.getId());
BeanUtil.copyPropertiesExcludeNullValue(oldEntity, entity);
sysUserService.update(oldEntity);
setSuccessJson("修改数据成功!");
} catch (Exception e) {
setFailJson("修改数据失败!");
LOG.error("修改数据失败!" + e.getMessage(), e);
}
return JSON;
}
public String delete() {
try {
if(StringUtils.isNotBlank(id)) {
sysUserService.deleteByIds(StringUtils.split(id.toString(), ","));
}
setSuccessJson("删除数据成功!");
} catch (Exception e) {
setFailJson("删除数据失败!");
LOG.error("删除数据失败!" + e.getMessage(), e);
}
return JSON;
}
public SysUser getEntity() {
return this.entity;
}
public void setEntity(SysUser entity) {
this.entity = entity;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
10、 前台调用
前台调用Action方法的方式:sys-user!list.do
上一篇: S2SH框架搭建—基于XML配置
下一篇: Atom解决快捷键冲突
推荐阅读
-
三、解决Spring MVC拦截器导致静态资源访问失败(基于java注解配置)
-
Spring+Spring MVC+Mybatis 框架整合开发(半注解半配置文件)
-
基于webpack4搭建的react项目框架的方法
-
Python实现的登录验证系统完整案例【基于搭建的MVC框架】
-
Python基于Flask框架配置依赖包信息的项目迁移部署
-
基于webpack实现多html页面开发框架五 开发环境配置 babel配置
-
Sping MVC不使用任何注解处理(jQuery)Ajax请求(基于XML配置)
-
基于 ASP.NET Core 2.0 WebAPI 后台框架搭建(0) - 目录概述
-
.NET Core的响应式框架,基于Ace Admin框架菜单导航,Bootstrap布局,fontAwesome图标,内嵌Iframe用EasyUI做数据绑定,动态配置列表,动态配置表单
-
Struts2基于注解的Action配置