使用 AppFuse 快速构建 J2EE 应用(二)

转载 2011年01月15日 21:17:00

其他功能

一个系统除了包含核心逻辑之外,还有其他一些辅助功能,它们也是非常重要的。下面,让我们来看看如何在 AppFuse 中开发这些功能。

语言国际化

如果你的系统不仅仅支持一种语言,那么就需要考虑这个问题。在 AppFuse 中,Resource Bundle 文件是位于 web/WEB-INF/classes 目录下的以 ApplicationResources 开头的 properties 文件。Tapestry 有自己的国际化文本机制。但是在 AppFuse 中,并不全是 Tapestry 页面,仍有些地方使用 jsp,而这些页面使用 JSTL 的 fmt 标签显示国际化文本。不过,AppFuse 已经将这二者的“源头”进行了整合,因此,对用户而言,只需要在 ApplicationResources*.properties 中定义需要国际化的文本。

但是,在 Eclipse 中可以看到,AppFuse 的 properties 文件默认的编码不是 UTF-8,而是 ISO-8859-1,这样会导致最后通过 native2ascii 转换后的文件都是 “???”,所以用户需要自己把这些文件转成 UTF-8。转换的方法很简单:在 properties 文件上点右键,在右键菜单上选择 Properties,打开属性窗口后,更改 “Text file encoding” 为 UTF-8。在修改编码前,最好先把已有的文字拷贝出来,转换好之后再粘贴回去,否则会导致原先翻译好的文字变成乱码。


图 12. ApplicationResources_zh_CN.properties 的属性窗口

AppFuse 在发布项目的时候,会自动用 native2ascii 转换这些资源文件。如果你想使用其他资源文件名,可以修改 web/WEB-INF/web.xml 中的 “javax.servlet.jsp.jstl.fmt.localizationContext” 的参数值。

页面布局和样式

使用 AppFuse,能够很方便的修改系统的整体布局和样式,因为 AppFuse 使用了一种强大的 “CSS框架”。项目创建好之后,在 web/styles 目录下,有三个目录:andreas01,puzzlewithstyle 和 simplicity。这些是 AppFuse 自带的三种主题,目录名即 CSS 框架的主题名。属于“管理员”角色的用户可以在登录后通过在 url 后面添加形如 "?theme=andreas01" 的参数更改系统使用的主题。如下图:


图 13. 应用了 “puzzlewithstyle” 的 myapp

系统默认使用的主题由 web/WEB-INF/web.xml 中的 “theme” 参数指定,AppFuse 默认使用的主题是 “simplicity”。更改或创建新的主题也很简单,只要在 web/styles 目录下,新建一个自己的目录,并参照已有主题的编写规范定义自己的主题。本文中,拷贝了 simplicity 目录,更名为 “mytheme”,然后将里面的字体颜色从“蓝色”基调改成了“绿色”基调,并修改 web.xml 中的 theme 参数值为 “mytheme”,这样 myapp 默认使用的就是 mytheme 的主题了,如图 8所示。你也可以从 http://css.appfuse.org/themes/ 得到更多关于 “CSS框架” 的信息。

系统安全

AppFuse 使用 Acegi 进行安全管理。Acegi 的配置信息位于 web/WEB-INF/classes/security.xml。事实上,Acegi 是被集成到 Spring 当中的,因此这个文件是 Spring 的配置文件格式。在 web/WEB-INF/web.xml 中,该文件被指定在应用启动前会被加载:


清单 5. web.xml 关于 Spring 配置文件的定义

                ...
<!-- Context Configuration locations for Spring XML files -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext-*.xml,/WEB-INF/security.xml</param-value>
    </context-param>
...

 

本文关于系统安全的实现如下:

  1. 在数据库中增加新的角色“hr”:编辑 myapp/metadata/sample-data.xml 文件,增加如下黑体的部分:

    清单 6. sample-data.xml 中角色 “hr” 的记录
                            ...
    <table name='role'>
        <column>id</column>
        <column>name</column>
        <column>description</column>
        <row>
          <value>1</value>
          <value>admin</value>
          <value><![CDATA[Administrator role (can edit Users)]]></value>
        </row>
        <row>
          <value>2</value>
          <value>user</value>
          <value><![CDATA[Default role for all Users]]></value>
        </row>
        <row>
          <value>3</value>
          <value>hr</value>
          <value><![CDATA[Role for employee mangement]]></value>
        </row>  
    </table>
    ...

    AppFuse 使用 dbunit 加载样本数据到数据库中,sample-data.xml 为 dbunit 提供样本数据定义。修改完 sample-data.xml,在 c:/opt/myapp/ 下运行 “ant db-load”,样本数据被重新加载。这样,我们就在数据库中定义了一个新的角色记录 “hr”。
  2. 定义角色名称的中文显示文本:在 myapp/sr/web/webapp/action/UserForm.java 的方法 pageBeginRender 中找到如下代码:
    // initialize drop-downs
    if (getAvailableRoles() == null) {
        List roles = (List) getServletContext().getAttribute(Constants.AVAILABLE_ROLES);
        setAvailableRoles(new RoleModel(roles));
    }

    将其做如下修改:
    // initialize drop-downs
    if (getAvailableRoles() == null) {
        List roles = (List) getServletContext().getAttribute(Constants.AVAILABLE_ROLES);
        for(int i=0;i<roles.size();i++){
           	LabelValue role=(LabelValue) roles.get(i);
           	role.setLabel(getText("rolelabel_"+role.getValue()));
        }
        setAvailableRoles(new RoleModel(roles));
    }

    并在 web/WEB-INF/classes/ApplicationResources_zh_CN.properties 中增加角色名称的定义:
    rolelabel_admin=系统管理员
    rolelabel_user=普通用户
    rolelabel_hr=人事管理

    AppFuse 默认在用户管理界面上显示的角色的名称是表 role 中的名称,这样无论切换到何种语言,角色名称都是 “admin”、"user"、“hr” 等等,角色名称不能根据 Locale 用相应的语言显示。因此,本文将角色的名称用 Resource Bundle 文件定义,数据库中存储 “key” 值。修改后的效果见 图 10。
  3. 配置“安全策略”:在 web/WEB-INF/security.xml 的 bean "filterInvocationInterceptor" 声明中增加如下“黑体”的一行:
    <bean id="filterInvocationInterceptor" 
    class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
            <property name="authenticationManager" ref="authenticationManager"/>
            <property name="accessDecisionManager" ref="accessDecisionManager"/>
            <property name="objectDefinitionSource">
                <value>
                    PATTERN_TYPE_APACHE_ANT
                    /clickstreams.jsp*=admin
                    /flushCache.*=admin
                    /passwordHint.html*=ROLE_ANONYMOUS,admin,user
                    /reload.*=admin
                    /signup.html*=ROLE_ANONYMOUS,admin,user
                    /users.html*=admin
                    /employees.html*=hr
                    /**/*.html*=admin,user
                </value>
            </property>
        </bean>

    “/employees.html*=hr” 的意思是:只有 hr 这个角色可以访问形如 “/employees.html*” 的 url。
  4. 将“员工信息维护”菜单关联到指定角色 hr:在 web/WEB-INF/menu-config.xml 中在 “EmployeeMenu” 的定义中增加 “roles='hr'”:
        <!--Employee-START-->
        <Menu name="EmployeeMenu" title="employeeList.title" page="/employees.html" roles="hr"/>
    |--10--------20--------30--------40--------50--------60--------70--------80--------9|
    |-------- XML error:  The previous line is longer than the max of 90 characters ---------|
        <!--Employee-END-->
    				  

    于是,“员工信息维护”的菜单入口只对属于“人事管理”角色的用户显示,对其他用户则隐藏。
  5. 分配角色 “hr” 给 tomcat:将“人事管理”角色分配给某一用户,例如 tomcat。则 tomcat能够看见并访问“员工信息维护”相关页面,而其他用户的界面上则没有“员工信息维护”这个菜单入口。并且,如果用户试图通过url访问employees.html的时候会看到如下页面:

    图 14. “访问被拒绝”页面

  6. 图 14是 AppFuse 提供的默认“访问被拒绝”页面,你可以通过修改 web/403.jsp 把它定制成自己喜欢的页面。

事务控制

AppFuse 利用 Spring 的事务管理机制。Spring 可以以声明的方式,对方法进行事务控制,并且可以根据实际的需要,调整控制粒度。“声明方式”的好处在于:核心代码只需要关注业务逻辑,而将事务控制完全交由配置文件管理,一方面是核心代码简洁清晰,另一方面也便于进行集中配置管理。

事务控制一般是定义在 service 类的方法上的。AppFuse 的所有 service 类都声明在 src/service/applicationContext-service.xml 中,该文件中包含有一个 “txProxyTemplate” bean 的声明,它定义了基本事务策略。其它的 service 类从 “txProxyTemplate” 继承,并可以“重写”事务策略。例如,AppFuse 对 userManager 的声明如下:

    <!-- Transaction template for Managers, from:
         http://blog.exis.com/colin/archives/2004/07/31/concise-transaction-definitions-spring-11/ -->
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error:  The previous line is longer than the max of 90 characters ---------|
    <bean id="txProxyTemplate" abstract="true"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager" ref="transactionManager"/>
        <property name="transactionAttributes">
            <props>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="remove*">PROPAGATION_REQUIRED</prop>
                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
            </props>
        </property>
    </bean>
    <!-- Transaction declarations for business services.  To apply a generic transaction proxy to
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error:  The previous line is longer than the max of 90 characters ---------|
         all managers, you might look into using the BeanNameAutoProxyCreator -->
    <bean id="userManager" parent="txProxyTemplate">
        <property name="target">
            <bean class="org.appfuse.service.impl.UserManagerImpl">
                <property name="userDao" ref="userDao"/>
            </bean>
        </property>
        <!-- Override default transaction attributes b/c of UserExistsException -->
        <property name="transactionAttributes">
            <props>
                <prop key="save*">PROPAGATION_REQUIRED,-UserExistsException</prop>
                <prop key="remove*">PROPAGATION_REQUIRED</prop>
                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
            </props>
        </property>
        <!-- This property is overriden in applicationContext-security.xml to add
             method-level role security -->
        <property name="preInterceptors">
            <list>
                <ref bean="userSecurityInterceptor"/>
            </list>
        </property>
    </bean>				
			

 

Spring 提供了大量的参数和选项使开发者能够灵活地管理事务。有关 Spring 使用方面的知识,请参阅 Spring 的文档。另外,《Spring in Action》也是一个不错的选择。

日志

AppFuse 集成了 Log4j 进行日志管理,log4j.properties 位于 web/WEB-INF/classes 目录下。AppFuse 已经在绝大多数基类(诸如,BasePage.java、BaseDaoHibernate.java 以及 BaseManager.java 等)中加入了如下用于输出日志的成员变量:

protected final Log log = LogFactory.getLog(getClass());
			

 

因此,开发者只需要在自己的代码中调用 log 的方法就可以了,例如:“log.debug("entered 'delete' method");”。

邮件

AppFuse 集成了 Spring 的发送邮件的功能。发送邮件需要用的参数,如主机、端口等信息在 web/WEB-INF/classes/mail.properties 中进行配置。和发送邮件相关的 bean 已经在 applicationContext-service.xml 中声明:mailEngine、mailSender、velocityEngine 以及 mailMessage。用户只需要在自己的类中 “注入” mainSender 的实例,就可以发送邮件了。具体使用方法,请参阅Spring的文档。

缓存

AppFuse 对缓存机制的支持源自 Hibernate 对缓存的支持。Hibernate 提供了对五种缓存机制的集成,AppFuse 默认提供了其中的两种:Ehcache 和 Oscache。开发者也可以根据需要自行添加和配置。Acegi 默认提供了对 Ehcache 支持的实现,所以 Ehcache 是较好的选择。ehcache.xml 和 oscache.properties 位于 web/WEB-INF/classes 中

相关文章推荐

AppFuse1.x快速构建J2ee应用

Appfuse是Matt Raible 开发的一个指导性的入门级J2EE框架,它对如何集成流行的Spring、Hibernate、ibatis、struts、Xdcolet、junit 等基础框架给出...
  • danwind
  • danwind
  • 2011年04月12日 17:33
  • 176

基于Appfuse 2.1快速构建工程的注意事项

好久没玩Appfuse了,最近因为工作的原因,需要快速构建两个工程原型作sample之用,于是又想到了Appfuse.自Appfuse 2.1发布后这还是第一次使用,以下罗列了使用Appfuse2.1...

使用Maven构建和部署J2EE应用程序的EAR文件

这篇文章,主要是技术上的整理,用来mark一下,用的时候参考。 一、新建项目 新建一个空的Maven Project项目 二、放入依赖 注:ear部署时如果里面有enti...

使用JSR365规范构建J2EE websocket服务端和客户端应用

JSR365是java制定的websocket编程规范,属于Java EE 7的一部分。websocket和socket一样,既有客户端编程,也有服务端编程,JSR365制定了websocket客户端...

使用 Eclipse 开发 J2EE 应用、使用 Eclipse 开发 EJB(二)

在第二部分"使用 Eclipse 开发 Web 应用"中,我们已经在 TestJ2EE 这个 J2EE 项目中添加了一个名为 MyEJB 的 EJB 模块。下面我们通过 Lomboz EJB Crea...

用Jetty快速开发J2EE应用

对于用Maven管理的项目,可以使用Maven的Jetty插件启动应用进行快速测试。项目的pom.xml配置如下: 4.0.0 com.cdai struts2-conf 0.0....
  • dc_726
  • dc_726
  • 2012年10月05日 22:15
  • 3392

【转】 J2EE应用高性能构建技巧_性能瓶颈

J2EE应用怎么才能提高性能呢,很多项目在由于一直沿用惯用的开发模式,赶时间,对性能需求都没放做重点。开发完了,搞台小型机挂上,简单的功能测试ok。下面几个方面收集希望能对项目开发带来点帮助J2EE应...

构建高性能J2EE应用的十个技巧

构建高性能的J2EE应用不但需要了解常用的实施技巧。下面介绍最常用的10种有效方法,可帮助架构设计师们快速成为这方面的专家。Java性能的基础—内存管理任何Java应用,单机的或J2EE的性能基础都可...

【转】构建高性能J2EE应用的10个技巧

构建高性能的J2EE应用不但需要了解常用的实施技巧。下面介绍最常用的10种有效方法,可帮助架构设计师们快速成为这方面的专家。     Java性能的基础----内存管理     任何Java应用,单机...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用 AppFuse 快速构建 J2EE 应用(二)
举报原因:
原因补充:

(最多只允许输入30个字)