framework开发手册
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Framework架构手册
前言
本框架基于Struts2.0+Spring2.5+Hibernate3.2架构所建,用于中小型企业网站或管理系统基础架构。
下面先简要介绍一下struts,spring,hibernate
●Struts简介
Struts是一个基于Sun J2EE平台的MVC框架,主要是采用Servlet和JSP技术来实现的。
Struts把Servlet、JSP、自定义标签和信息资源(message resources)整合到一个统一的框架中,开发人员利用其进行开发时不用再自己编码实现全套MVC模式,极大的节省了时间,所以说Struts是一个非常不错的应用框架。
●Spring简介
Spring是一个解决了许多在J2EE开发中常见的问题的强大框架。
Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯。
Spring的架构基础是基于使用JavaBean属性的Inversion of Control容器。
然而,这仅仅是完整图景中的一部分:Spring在使用IoC容器作为构建完关注所有架构层的完整解决方案方面是独一无二的。
Spring提供了唯一的数据访问抽象,包括简单和有效率的JDBC框架,极大的改进了效率并且减少了可能的错误。
Spring的数据访问架构还集成了Hibernate和其他O/R mapping解决方案。
Spring还提供了唯一的事务管理抽象,它能够在各种底层事务管理技术,例如JTA 或者JDBC事务提供一个一致的编程模型。
Spring提供了一个用标准Java语言编写的AOP 框架,它给POJOs提供了声明式的事务管理和其他企业事务--如果你需要--还能实现你自己的aspects。
这个框架足够强大,使得应用程序能够抛开EJB的复杂性,同时享受着和传统EJB相关的关键服务。
Spring还提供了可以和IoC容器集成的强大而灵活的MVC Web框架。
●Hibrenate简介
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序实用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。
在本架构中,struts承担的角色是在Web层的MVC模式的应用,不涉及具体业务逻辑的处理,只是页面显示和流程的控制,输入输出参数的封装等功能。
Spring承担的角色是对应用中各层次的接口和类采用IOC模式进行统一管理配置,同时,还采用AOP和Spring对事务的处理机制来管理事务,并根据Spring与Hibernate的集成,调用Spring提供的HibernateTemplate来处理底层DAO。
Hibernate承担的角色是底层数据库实体对象的封装,以及实体之间关系的映射,本架构中采用注解来进行O-R Mapping。
第一章技术架构
如图所示,系统划分为Model Bean(PO),DAO,Business Logic(Service),WEB四个主要层次,其中PO可在各层使用。
基础架构如下图所示,在程序开发时要在工程中加入该基础架构,并在其上做扩
基础架构图
1Model Bean(PO)层
PO(Persistence Object),持久化对象,为我们从项目中抽象出的实体模型,一般对应与数据库的一个表,其中实体中的属性与数据库表中的字段相对应。
在以上几个层次中都会用到PO,如在web层中会用来接受前台表单提交的数据,在DAO层中会利用hibernate对PO进行数据操作。
由于在项目中用到了hibernate,因此在生成PO后,会进行hibernate的配置。
1.1类图
注:红色线条的类代表框架里的基类,黑色线条的类代表具体应用的Model Bean
1.2.样例代码
public abstract class BaseModel implements Serializable {
protected final Log logger = LogFactory.getLog(getClass());
}
1.3.hibernate的配置
1.3.1.基于hibernate annotation的配置
例:
@Entity
@Table(name = "otc_book")
public class OtcBook extends com.otc.framework.model.BaseModel implements
java.io.Serializable {
// Fields
/**
*
*/
private static final long serialVersionUID = 1L;
//定义主键
@Id
@GeneratedValue
private Integer id;
private String bookname;
private Long price;
//定义单项一对多的关系
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE },
fetch = ZY, mappedBy = "books") private Set<OtcOrder> orders;
/**default constructor*/
public OtcBook() {
if (null == orders)
orders = new HashSet<OtcOrder>();
}
/**full constructor*/
public OtcBook(String bookname, Long price) { this.bookname = bookname;
this.price = price;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getBookname() {
return this.bookname;
}
public void setBookname(String bookname) { this.bookname = bookname;
}
public Long getPrice() {
return this.price;
}
public void setPrice(Long price) {
this.price = price;
}
public Set<OtcOrder> getOrders() {
return orders;
}
public void setOrders(Set<OtcOrder> orders) {
this.orders = orders;
}
}
每个model bean都继承框架里的BaseModel,并根据具体实体关系添加hibernate-annotation注解,就不需要再配置每个model bean的.hbm.xml文件了。
1.4.spring配置
<!—-定义hibernate的sessionFactory,相当于hibernate.hbm.xml-->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSe ssionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<!—-声明业务model bean-->
<property name="annotatedClasses">
<list>
<value>com.otc.demo.model.OtcCustomer</value>
<value>com.otc.demo.model.OtcOrder</value>
<value>com.otc.demo.model.OtcBook</value>
</list>
</property>
</bean>
2 DAO层
负责Model Bean以增删改查为主的底层数据库操作
2.1类图
BeseDAO
OtcBookDAO
注:其中uses表示接口的实现
2.2样例代码
package com.otc.framework.dao;
import java.io.Serializable;
import java.util.List;
public interface BaseDAO {
@SuppressWarnings("unchecked")
public List getObjects(Class clazz);
@SuppressWarnings("unchecked")
public Object getObject(Class clazz, Serializable id);
public void saveObject(Object o);
@SuppressWarnings("unchecked")
public void removeObject(Class clazz, Serializable id);
@SuppressWarnings("unchecked")
public List findObjectByProperties(String hql);
@SuppressWarnings("unchecked")
public List findObjectByProperties(String hql, Object[] values); }
2.3 DAO Hibernate的实现
DAO接口的hibernate实现,需要继承BaseDAOHibernate,实现相应的DAO接口
例:
import java.io.Serializable;
import java.util.List;
import mons.logging.Log;
import mons.logging.LogFactory;
import
org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.otc.framework.dao.BaseDAO;
public class BaseDAOHibernate extends HibernateDaoSupport implements BaseDAO {
protected final Log logger = LogFactory.getLog(getClass());
/*
* (non-Javadoc)
*
* @see com.otc.framework.dao.BaseDAO#getObject(ng.Class, * java.io.Serializable)
*/
@SuppressWarnings("unchecked")
public Object getObject(Class clazz, Serializable id) { return getHibernateTemplate().get(clazz, id);
}
/*
* (non-Javadoc)
*
* @see com.otc.framework.dao.BaseDAO#getObjects(ng.Class) */
@SuppressWarnings("unchecked")
public List getObjects(Class clazz) {
return getHibernateTemplate().loadAll(clazz);
}
/*
* (non-Javadoc)
*
* @see
com.otc.framework.dao.BaseDAO#findObjectByProperties(ng.String )
*/
@SuppressWarnings("unchecked")
public List findObjectByProperties(String hql) {
return getHibernateTemplate().find(hql);
}
/*
* (non-Javadoc)
*
* @see
com.otc.framework.dao.BaseDAO#findObjectByProperties(ng.String ,ng.Object[])
*/
@SuppressWarnings("unchecked")
public List findObjectByProperties(String hql, Object[] values) { return getHibernateTemplate().find(hql, values);
}
/*
* (non-Javadoc)
*
* @see com.otc.framework.dao.BaseDAO#removeObject(ng.Class, * java.io.Serializable)
*/
@SuppressWarnings("unchecked")
public void removeObject(Class clazz, Serializable id) { getHibernateTemplate().delete(getObject(clazz, id));
}
/*
* (non-Javadoc)
*
* @see com.otc.framework.dao.BaseDAO#saveObject(ng.Object) */
public void saveObject(Object o) {
getHibernateTemplate().saveOrUpdate(o);
}
}
基础架构中的BaseDAOHibernate为我们提供了基于PO的增删改查以及分页等功能。
1.4spring的配置
为应用中的dao注入具体实现类以及sessionFactory
<bean id="OtcBookDAO"
class="com.otc.demo.dao.impl.OtcBookDAOImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
3 Service层
针对用例,提供基于需求的方法接口。
3.1 类图
BookManager
注:其中MangerSupport类继承BaseManagerImpl,并将应用中所有DAO接口都作为其属性,通过spring ioc依赖注入,其他业务应用Service都继承于它,这样每个Service都可以得到所有的DAO实现。
3.2样例代码
例:ManagerSupport类
import com.otc.demo.dao.OtcBookDAO;
import com.otc.demo.dao.OtcCustomerDAO;
import com.otc.demo.dao.OtcOrderDAO;
import com.otc.framework.service.impl.BaseManagerImpl;
public class ManagerSupport extends BaseManagerImpl {
//所有模块中的DAO
protected OtcCustomerDAO otcCustomerdao;
protected OtcBookDAO otcBookdao;
protected OtcOrderDAO otcOrderdao;
public OtcCustomerDAO getOtcCustomerdao() {
return otcCustomerdao;
}
public void setOtcCustomerdao(OtcCustomerDAO otcCustomerdao) { this.otcCustomerdao = otcCustomerdao;
}
public OtcBookDAO getOtcBookdao() {
return otcBookdao;
}
public void setOtcBookdao(OtcBookDAO otcBookdao) {
this.otcBookdao = otcBookdao;
}
public OtcOrderDAO getOtcOrderdao() {
return otcOrderdao;
}
public void setOtcOrderdao(OtcOrderDAO otcOrderdao) { this.otcOrderdao = otcOrderdao;
}
}
public class BookManagerImpl extends ManagerSupport implements BookManager {
public void addBook(OtcBook book) {
if (logger.isDebugEnabled()) {
logger.debug("bookname:" + book.getBookname());
logger.debug("price:" + book.getPrice());
}
otcBookdao.insertBook(book);
}
public OtcBook getBook(int id) {
return otcBookdao.getOtcBook(id);
}
public void modifyBook(OtcBook book) {
otcBookdao.updateBook(book);
}
@SuppressWarnings("unchecked")
public List<OtcBook> queryBooks(HashMap hm) {
return otcBookdao.queryOtcBooks(hm);
}
public void removeBook(int id) throws BusinessException { OtcBook book = otcBookdao.getOtcBook(id);
int count = book.getOrders().size();
if (logger.isDebugEnabled())
logger.debug("count:" + count);
if (count > 0) {
throw new BusinessException("0001");
} else {
otcBookdao.deleteBook(id);
}
}
}
3.3 Service层实现
根据具体的业务模块划分每个Service层,都提供相应的接口,并有其相应的实现,实现类都必须继承ManagerSupport,用以得到DAO层的句柄。
若Service层的各个方法的输入参数比较多的话,需要通过Map封装输入参数。
返回结果一般可为Collection。
3.4 spring配置
<!--继承ManagerSupport,以得到所有DAO的实现-->
<bean id="BookManager" parent="ManagerSupport"
class="com.otc.demo.service.impl.BookManagerImpl"/>
<!—配置所有的DAO-->
<bean id="ManagerSupport"
class="com.otc.demo.service.base.ManagerSupport" abstract="true"> <property name="otcCustomerdao">
<ref bean="OtcCustomerDAO" />
</property>
<property name="otcBookdao">
<ref bean="OtcBookDAO" />
</property>
<property name="otcOrderdao">
<ref bean="OtcOrderDAO" />
</property>
</bean>
4 Web层
基于Struts2的MVC模型,本框架提供BaseAction基类,该基类继承Struts2中的ActionSupport,并实现SessionAware,ServletRequestAware,ServletResponseAware接口。
通过这些接口可以得到session,servletRequest,servletResponse对象。
本框架同时还提供ErrorAction类,用于统一处理系统业务异常。
4.1 类图
ServletRequestAware
注:其中蓝色线条为struts2提供的基类和接口,红色线条为本框架提供的基类,黑色线条代表具体的业务逻辑action,根据struts2的机制,可以在一个Action中写多条具体的业务方法,根据具体的业务逻辑添加业务方法。
4.2 样例代码
import java.util.HashMap;
import ng.StringUtils;
import com.otc.demo.model.OtcCustomer;
import erManager;
import com.otc.framework.web.FrameworkWebSessionContextKey;
import com.otc.framework.web.struts.actions.BaseAction;
public class LoginAction extends BaseAction {
//注入名为userManage的Service
private UserManager userManager;
//实体的属性
private String username;
private String password;
private String message;
/**
*
*/
private static final long serialVersionUID = 1L;
@SuppressWarnings("unchecked")
public String execute() {
if (StringUtils.isEmpty(username) ||
StringUtils.isEmpty(password)) {
return INPUT;
}
if (logger.isDebugEnabled()) {
logger.debug("username:" + username);
logger.debug("password:" + password);
}
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("username", username);
hm.put("password", password);
OtcCustomer userInfo = userManager.login(hm);
if (null != userInfo) {
session.put(ERNAME, userInfo
.getUsername());
session.put(ERINFO, userInfo);
return SUCCESS;
} else {
message = getText("login.validation.message.text");
return INPUT;
}
}
public String getPassword() {
return password;
}
public void setUserManager(UserManager userManager) {
erManager = userManager;
}
public void setUsername(String username) {
ername = username;
}
public void setPassword(String password) {
this.password = password;
}
public UserManager getUserManager() {
return userManager;
}
public String getUsername() {
return username;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
在struts机制中,每个Action都是一个类似Model Bean的实体类。
定义输入输出属性时,都分别有get/set方法,Action中具体的业务方法,都是返回String类型的,在struts.xml文件中配置不同的业务方法。
4.3 struts2配置
例:一般在classpath下的struts.xml文件中配置如下
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"/dtds/struts-2.0.dtd">
<struts>
<!--导入其他struts配置文件-->
<include file="struts-default.xml" />
<package name="com.otc.demo.web.struts2.actions"
extends="struts-default">
<interceptors>
<!--定义一个名为loginInterceptor的拦截器-->
<interceptor name="loginInterceptor"
class="com.otc.framework.web.struts.interceptor.LogonInterceptor"> <param name="registerActionName">register</param>
<param name="loginActionName">login</param>
<param name="forwardLoginPage">login</param>
</interceptor>
<!--定义一个包含登陆检查的拦截器栈-->
<interceptor-stack name="mydefaultStack">
<!--配置内建默认拦截器-->
<interceptor-ref name="defaultStack" />
<!--配置自定义的拦截器-->
<interceptor-ref name="loginInterceptor" />
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="mydefaultStack" />
<default-action-ref name="Error" />
<global-results>
<result name="error">/error.jsp</result>
<result name="login" type="redirect-action">login</result>
<result name="exception">/failure.jsp</result>
<result name="businessException">/error.jsp</result> </global-results>
<global-exception-mappings>
<exception-mapping result="exception"
exception="ng.Exception"/>
<exception-mapping result="businessException"
exception="com.otc.framework.exception.BusinessException"/> </global-exception-mappings>
<action name="Error"
class="com.otc.framework.web.struts.actions.ErrorAction">
<result>/error.jsp</result>
</action>
<action name="login" class="LoginAction">
<result name="success"
type="redirect-action">book_list</result>
<result name="input">login.jsp</result>
<result name="error">login.jsp</result>
</action>
<action name="register_*" method="{1}" class="RegisterAction"> <result name="forward_register">register.jsp</result>
<result name="register_success"
type="redirect-action">book_list</result>
<result name="input"
type="redirect-action">register_forwardRegisterPage</result> </action>
<action name="logout" class="LogoutAction">
<result>login.jsp</result>
</action>
<action name="book_*" method="{1}" class="BookAction">
<result>jsp/queryBooks.jsp</result>
<result name="add_success"
type="redirect-action">book_list</result>
<result name="remove_success"
type="redirect-action">book_list</result>
<result name="edit_success"
type="redirect-action">book_list</result>
<result
name="getBookByID_success">jsp/editBook.jsp</result>
<result name="input">addBook.jsp</result>
</action>
<action name="user_*" method="{1}" class="UserAction">
<result name="buy_success"
type="redirect-action">book_list</result>
<result name="forward_queryOrders"
type="redirect-action">user_queryOrders</result>
<result
name="queryOrders_success">jsp/queryOrders.jsp</result>
</action>
</package>
</struts>
注:该配置中自定义了一个Interceptor,定义了两种异常处理方式和统一的Error处理机制。
其中每个具体的Action的实现类都是在spring配置的,如下。
在user,register,book这些Action的配置文件中都使用了通配符,这是依据struts2的通配符机制做的,具体可参考有关struts2的相关资料。
4.4 spring 配置
<bean id="LoginAction"
class="com.otc.demo.web.struts2.actions.LoginAction"
scope="prototype">
<property name="userManager">
<ref bean="UserManager" />
</property>
</bean>
<bean id="RegisterAction"
class="com.otc.demo.web.struts2.actions.RegisterAction"
scope="prototype">
<property name="userManager">
<ref bean="UserManager" />
</property>
</bean>
这里每个bean定义标签中都加入了scope=”prototype”,标志为每次业务请求都会生成一个action实例,从而保证请求的线程安全。
4.5 web层的国际化
依据struts2的国际化方法,需要在classpath下定义的struts.properties文件中定义好具体的Resource.然后可在classpath下依据struts2的国际化机制,分层逐级逐级有底向上查找资源文件。
Struts.properties例:
struts.objectFactory=spring
struts.devMode=true
struts.custom.i18n.resources=ApplicationResources
struts.i18n.encoding=utf-8
struts.i18n.reload=true
注:在上面的struts.custom.i18n.resources的key下定义了ApplicationResources的资源文件名,在应用中把它作为默认的资源文件。
具体struts中每个key的含义请查找有关struts2资料。
ApplicationResources.properties文件的划分,可根据不同语言来划分。
例如:
ApplicationResources_en.properties(英文资源,包括en_US,en_GB等以英文为主的资源) ApplicationResources_zh.properties(中文资源,包括zh_CN,zh_TW等以中文为主的资源) ApplicationResources.properties(为默认资源文件)
例:英文资源文件内容如下:
#common source of page
common.button.ok.value=OK
common.button.cancel.value=Cancel
common.button.query.value=Query
common.button.add.value=Add
common.button.edit.value=Edit
common.button.delete.value=Delete
相应的中文资源文件如下:
#common source of page
common.button.ok.value=确定
common.button.cancel.value=取消
common.button.query.value=查询
common.button.add.value=添加
common.button.edit.value=修改
common.button.delete.value=删除
第二章异常,错误码
本框架提供BusinessException,FrameworkRuntimeException,FrameworkException三种异常。
其中BusinessException继承FrameworkException,并提供错误号接口,该异常主要用于应用层,捕获所有具有业务性质的异常。
最终由struts2的异常拦截器捕获所有异常,并可以通过配置文件统一处理。
1 类图
2 错误码
错误码主要用于业务异常,根据业务的需要抛出指定错误码的BusinessException,由Struts2 Interceptor统一拦截。
考虑到国际化的因素,错误码保存在classpath下以ErrorCodeResources 文件名开头的资源文件中,并根据不同的语言,提供不同的资源文件。
例:
ErrorCodeResources.properties(默认的资源文件)
ErrorCodeResources_en.properties(英文资源)
ErrorCodeResources_zh.properties(中文资源)
ErrorCodeResources_en.properties内容:
#Business ErrorCode
0001=The book has orders,don't delete it.
相应中文文件中的内容:
#Business ErrorCode
0001=该图书存在订单,不能删除
其中“0001”为错误码编号,等号后面为错误码对应的描述,用于显示到页面上
3 struts.xml中异常配置
<global-results>
<result name="error">/error.jsp</result>
<result name="login" type="redirect-action">
login
</result>
<result name="exception">/failure.jsp</result>
<result name="businessException">/error.jsp</result> </global-results>
<global-exception-mappings>
<exception-mapping result="exception"
exception="ng.Exception"/>
<exception-mapping result="businessException"
exception="com.otc.framework.exception.BusinessException"/> </global-exception-mappings>
如上例代码所示,其中分为两种异常,分别有不同的页面显示。
Exception由failure.jsp显示,businessException由error.jsp显示
第三章日志
使用apache log4j,配置基于文件系统的日志机制,每次都提供了log4j句柄,开发人员可直接使用。
1 日志记录原则
每条记录需要包含业务key信息,以便于日志中每次流程的追查。
根据不同的日志级别,在每次写日志时,需要进行日志级别的判断。
如:
Debug级别的日志判断
If(logger.isDebugEnabled()){
Logger.debug(“……..”);
}
需要每次都添加相应的日志级别的判断。
2 日志划分原则
目标:可根据错误日志快速定位问题
因此指定日志原则:日志划分为多个重要级别,并可以单独打开或关闭。
可以考虑多维划分
日志模块,根据需要可划分为framework和业务应用的日志模块,可以添加其他第三方开源软件的日志,例如:spring,hibernate,struts等,便于追查由于程序问题而导致的出错原因。
3 log4j配置文件样例代码
#log4j.rootLogger=ERROR, CA
log4j.rootLogger=ERROR,Root
.springframework=INFO,OrgSpring
.hibernate=INFO,OrgHibernate
.apache.struts2=INFO,OrgStruts
.opensymphony.xwork2=INFO,OrgXwork
.otc.framework=DEBUG,OTCFramework
.otc.demo=DEBUG,OTCDemo
# CA is set to be a ConsoleAppender
#log4j.appender.CA=org.apache.log4j.ConsoleAppender
#yout=org.apache.log4j.PatternLayout
#yout.ConversionPattern=[%p] %-d{yyyy-MM-dd
HH:mm:ss} [%t] [%c.%M:%L] %m%n
#log4j.appender.Threshold=DEBUG
# OTC is set to be a RollingFileAppender.
log4j.appender.Root=org.apache.log4j.RollingFileAppender
log4j.appender.Root.File=otc/otc.log
log4j.appender.Root.MaxFileSize=10000KB
log4j.appender.Root.MaxBackupIndex=10
yout=org.apache.log4j.PatternLayout
yout.ConversionPattern=[%p] %-d{yyyy-MM-dd
HH:mm:ss} [%t] [%c.%M:%L] %m%n
log4j.appender.OTCFramework=org.apache.log4j.RollingFileAppender
log4j.appender.OTCFramework.File=otc/otc_framework.log
log4j.appender.OTCFramework.MaxFileSize=10000KB
log4j.appender.OTCFramework.MaxBackupIndex=10
yout=org.apache.log4j.PatternLayout
yout.ConversionPattern=[%p] %-d{yyyy-MM -dd HH:mm:ss} [%t] [%c.%M:%L] %m%n
log4j.appender.OTCDemo=org.apache.log4j.RollingFileAppender
log4j.appender.OTCDemo.File=otc/otc_demo.log
log4j.appender.OTCDemo.MaxFileSize=10000KB
log4j.appender.OTCDemo.MaxBackupIndex=10
yout=org.apache.log4j.PatternLayout
yout.ConversionPattern=[%p] %-d{yyyy-MM-dd HH:mm:ss} [%t] [%c.%M:%L] %m%n
Spring=org.apache.log4j.RollingFileAppender
Spring.File=otc/spring.log
Spring.MaxFileSize=10000KB
Spring.MaxBackupIndex=10
yout=org.apache.log4j.PatternLayout
yout.ConversionPattern=[%p] %-d{yyyy-MM-dd HH:mm:ss} [%t] [%c.%M:%L] %m%n
Hibernate=org.apache.log4j.RollingFileAppender
Hibernate.File=otc/hibernate.log
Hibernate.MaxFileSize=10000KB
Hibernate.MaxBackupIndex=10
yout=org.apache.log4j.PatternLayout
yout.ConversionPattern=[%p] %-d{yyyy-MM -dd HH:mm:ss} [%t] [%c.%M:%L] %m%n
Struts=org.apache.log4j.RollingFileAppender
Struts.File=otc/struts.log
Struts.MaxFileSize=10000KB
Struts.MaxBackupIndex=10
yout=org.apache.log4j.PatternLayout
yout.ConversionPattern=[%p] %-d{yyyy-MM-dd HH:mm:ss} [%t] [%c.%M:%L] %m%n
Xwork=org.apache.log4j.RollingFileAppender
Xwork.File=otc/xwork.log
Xwork.MaxFileSize=10000KB
Xwork.MaxBackupIndex=10
yout=org.apache.log4j.PatternLayout
yout.ConversionPattern=[%p] %-d{yyyy-MM-dd HH:mm:ss} [%t] [%c.%M:%L] %m%n
注:本配置中定义了framework和demo的两类日志,还定义了第三方开源软件struts,spring,hibernate,xwork的日志和总日志otc.log。
并可以根据需要定义不同的日志级别。
例:第三分软件多为Info级别,framework,demo为debug级别
第四章事务
目前事务主要通过spring的事务机制来处理。
根据层次划分,通过拦截器在Service层统一拦截处理事务,因为考虑到Service层业务逻辑有可能处理多个DAO,同时,Service层的方法都是针对每个业务展开的,便于保证事务的一致性。
注:事务由spring自动管理,并自动提交事务,如需要事务回滚,需抛出RuntimeException。
样例代码
<!--定义事务传播特性 -->
<bean id="matchAllWithPropReq"
class="MatchTrans actionAttributeSource">
<property name="properties">
<value>*=PROPAGATION_REQUIRED</value>
</property>
</bean>
<bean id="matchAllTxInterceptor"
class="org.springframework.transaction.interceptor.TransactionInt erceptor">
<property name="transactionManager">
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionMan ager">
<property name="sessionFactory" ref="sessionFactory" /> </bean>
</property>
<property name="transactionAttributeSource">
<ref bean="matchAllWithPropReq" />
</property>
</bean>
<bean id="autoProxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoPr oxyCreator">
<!--定义哪些service应用事务 -->
<property name="beanNames">
<value>*Manager</value>
</property>
<property name="interceptorNames">
<list>
<value>matchAllTxInterceptor</value>
</list>
</property>
</bean>
第五章国际化
1 Web页面国际化
1.1 静态文字国际化
使用struts2的国际化机制,在classpath下根据语言需要定义相应的资源文件
具体使用内容和方法,参阅第一章4.5部分
1.2 可管理文字国际化
主要是指界面中存在的,需要用户可维护的文字。
(可根据需要添加)
1.3图片国际化
(可根据需要添加)
2 国际化信息的缓存
(可根据需要添加)
第六章用户身份验证
系统需要验证用户身份,才允许用户登入系统,进行其他业务操作,因此理论上说,无论用户通过.jsp, .html, .action等其他文件扩展名,都无法进入。
Struts2提供了拦截器机制,可通过自定的拦截器,拦截所有的action(除登陆和注册),并可以通过自定义的filter过滤掉.jsp, .html文件
样例代码
在struts.xml文件中配置的拦截器
<interceptors>
<!--定义一个名为loginInterceptor的拦截器-->
<interceptor name="loginInterceptor"
class="com.otc.framework.web.struts.interceptor.LogonInterceptor"> <param name="registerActionName">register</param>
<param name="loginActionName">login</param>
<param name="forwardLoginPage">login</param>
</interceptor>
<!--定义一个包含登陆检查的拦截器栈-->
<interceptor-stack name="mydefaultStack">
<!--配置内建默认拦截器-->
<interceptor-ref name="defaultStack" />
<!--配置自定义的拦截器-->
<interceptor-ref name="loginInterceptor" />
</interceptor-stack>
</interceptors>
com.otc.framework.web.struts.interceptor.LogonInterceptor拦截器样例代码
package com.otc.framework.web.struts.interceptor;
import java.util.Map;
import mons.logging.Log;
import mons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor; import com.otc.framework.web.FrameworkWebSessionContextKey;
public class LogonInterceptor extends AbstractInterceptor {
private String registerActionName = "register";
private String loginActionName = "login";
private String forwardLoginPage = "login";
private static final Log logger =
LogFactory.getLog(LogonInterceptor.class);
/**
*
*/
private static final long serialVersionUID = 1L;
/*
* (non-Javadoc)
*
* @see
com.opensymphony.xwork2.interceptor.AbstractInterceptor#intercept(com .opensymphony.xwork2.ActionInvocation)
*/
@Override
@SuppressWarnings("unchecked")
public String intercept(ActionInvocation invocation) throws Exception {
String action_name =
invocation.getInvocationContext().getName();
if (logger.isDebugEnabled()) {
logger.debug("action name:" + action_name);
logger.debug("registerActionName:" + registerActionName);
logger.debug("action_name.indexOf(registerActionName):"
+ action_name.indexOf(registerActionName));
}
if (loginActionName.equals(action_name)
|| action_name.indexOf(registerActionName) != -1) { return invocation.invoke();
} else {
ActionContext ac = invocation.getInvocationContext();
Map session = (Map) ac.get(ServletActionContext.SESSION);
if (logger.isDebugEnabled())
logger.debug("struts2 session is " + session);
if (session == null) {
return forwardLoginPage;
} else {
String username = (String) session
.get(ERNAME);
if (logger.isDebugEnabled())
logger.debug("username:" + username);
if (username == null) {
return forwardLoginPage;
} else {
return invocation.invoke();。