原创技术高手--参赛文章
标题:基于J2EE的Blog平台 标题:基于J2EE的Blog平台
[评论]
作者:xuefengl(dev2dev ID)
摘要:

本文讲述如何在J2EE平台上创建一个Blog系统,以.Text的功能和界面为原型,Springframework为框架,实现一个运行在WebLogic Server上的灵活的多层结构的Blog平台。

目录:

1. 设计目标
2. 开发环境
2.1. 选择平台和框架
2.2. 配置服务器
2.3. 编写Ant脚本
3. 系统设计
3.1. 持久层设计
3.1.1. 设计Domain对象
3.1.2. 配置iBatis
3.1.3. 使用DAO模式
3.2. 逻辑层设计
3.3. Web层设计
3.3.1. 使用MVC模式
3.3.2. 实现Skin
3.3.3. 实现图片上传
3.3.4. 实现RSS
4. 测试
5. 总结
6. 源代码下载
7. 相关资源下载
8. 参考
9. 关于作者

设计目标

Blog(WebLog)在Internet上越来越流行。许多网友都有了自己的Blog,通过Blog展示自己,结识更过的网友。比较著名的Blog平台是基于ASP.net的开源项目.Text。但是它的逻辑全部以存储过程的形式放在数据库中。虽然存储过程能大大提高数据操作的效率,但是存储过程本身是结构化的程序,无法发挥面向对象的威力,也不便于实现代码复用。因此,我决定实现一个基于J2EE体系的多层结构的Blog平台,功能和界面和.Text非常类似,暂命名为Crystal Blog。实现的功能有:多用户支持;发表和编辑文章;上传图片;添加链接等常见功能。界面如下:


标题:基于J2EE的Blog平台

选择平台和框架

由于使用J2EE平台,我们准备采用WebLogic Server 8.1作为运行平台,使用WebLogic Workshop8.1这个强大的集成化IDE作为开发工具。
数据库选择MS SQL Server 2000 SP3,建立一个名为blog的数据库存储所有的用户数据。由于我们并没有针对特定数据库编码,稍后我们会使用其他数据库测试。
在系统设计之前,选择一个优秀的框架能大大提高开发效率。Spring是一个轻量级的J2EE框架。它覆盖了从后台数据库的JDBC封装到前台Web框架的几乎所有方面。并且,Spring的各个模块耦合非常松散,我们既可以用它作为整个应用程序的框架,也可以仅仅使用它的某一个模块。此外,Spring非常强大的集成功能使我们可以轻易地集成Struts编写的Web端,或者使用Hibernate作为后端的O/R Mapping方案。
Spring的核心思想便是IoC和AOP,Spring本身是一个轻量级容器,和EJB容器不同,Spring的组件就是普通的Java Bean,这使得单元测试可以不再依赖容器,编写更加容易。Spring负责管理所有的Java Bean组件,同样支持声明式的事务管理。我们只需要编写好Java Bean组件,然后将它们“装配”起来就可以了,组件的初始化和管理均由Spring完成,只需在配置文件中声明即可。这种方式最大的优点是各组件的耦合极为松散,并且无需我们自己实现Singleton模式。
由于后台要使用关系数据库存储数据,使用O/R Mapping必不可少。iBatis是又一个类似于Hibernate的O/R Mapping方案,特点是小巧,配置简单,查询灵活,完全符合我们的要求。
除了Spring和iBatis,用到的第三方组件还有有:common-file-upload 1.0,RSSLibJ1.0 RC2。
由于使用Spring这个轻量级框架,就无需EJB服务器,只需要Web服务器即可。因此,系统可以运行在WebLogic Server,Tomcat和Resin等支持Servlet和JSP的Web服务器上。

配置服务器

在WebLogic中新建一个Configuration,命名为blog,添加一个数据源,命名为jdbc/blog:

整个应用程序的目录结构如下:
crystalblog/
+ doc/ (存放API文档)
+ report/ (存放JUnit测试结果)
+ src/ (存放java源程序)
+ web/ (web目录)
| + manage/ (存放blog管理页)
| + skin/ (存放blog界面页)
| + upload/ (存放用户上传的图片)
| + WEB-INF/
| + classes/ (存放编译的class文件)
| + lib/ (存放用到的所有jar文件)
| + c.tld (使用jstl必须的文件)
| + dispatcher-servlet.xml (Spring配置文件)
| + web.xml (标准web配置文件)
+ blog.war (打包的可部署应用)
+ build.xml (ant脚本)


...

单元测试的结果以文本文件存放在report目录中。如果测试通过,下一步便是打包成blog.war文件。接着把应用部署到服务器上,直接将web目录的内容复制到%BEA_HOME%/user_projects/domains/blogdomain/applications/blog/目录下即可。如果要在Tomcat上部署,直接将整个web目录复制到%TOMCAT%/webapps/blog/下。
最后,如果需要,可以用javadoc生成api文档。

系统设计

Crystal Blog共分成三层结构:后台数据持久层,采用DAO模式;中间逻辑层,采用Facade模式;前端Web层,采用MVC结构,使用JSP作为视图。以下是Rational Rose的UML图:

标题:基于J2EE的Blog平台

设计Domain对象

Domain层是抽象出的实体。根据我们要实现的功能,设计以下实体,它们都是普通的Java Bean:
Account:封装一个用户,包括用户ID,用户名,口令,用户设置等等。
Category:封装一个分类,一共有3种Category,分别用来管理Article,Image和Link,一个Account对应多个Category。
Article:封装一篇文章,包括Title,Summary,Content等等,一个Category对应多个Article。
Feedback:封装一个回复,包括Title,Username,Url和Content,一个Article对应多个Feedback。
Image:封装一个图片,Image只包含图片信息(ImageId,Type),具体的图片是以用户上传到服务器的文件的形式存储的。一个Category对应多个Image。

Link:封装一个链接,和Category是多对一的关系。有Title,Url,Rss等属性。
Message:封装一个消息,使其他用户在不知道Email地址的情况下能够通过系统发送邮件给某个用户。
最后,为了唯一标识每条数据库记录,我们需要一个主键。在MS SQL Server和Oracle中可以使用自动递增的主键生成方式。但是很多数据库不支持自动递增的主键,考虑到移植性,我们自己定义一个Sequence表,用于生成递增的主键。Sequence表有且仅有7条记录,分别记录Account到Message对象的当前最大主键值。系统启动时,由SqlConfig负责初始化Sequence表。
SequenceDao负责提供下一个主键,为了提高效率,一次缓存10个主键。

配置iBatis

接下来,使用iBatis实现O/R Mapping。首先从http://www.ibatis.com下载iBatis 2.0,将所需的jar文件复制到web/WEB-INF/lib/目录下。iBatis使用XML配置数据库表到Java对象的映射,先编写一个sql-map-config.xml:
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<settings cacheModelsEnabled="false" enhancementEnabled="true"
lazyLoadingEnabled="true" maxRequests="32"
maxSessions="10" maxTransactions="5"
useStatementNamespaces="false"
/>
<transactionManager type="JDBC">
<dataSource type="JNDI">
<property name="DataSource" value="jdbc/blog" />
</dataSource>
</transactionManager>
<!-- 如果有其他xml配置文件,可以包含进来 -->
<sqlMap resource="Account.xml" />
</sqlMapConfig>
将sql-map-config.xml放到web/WEB-INF/classes/目录下,iBatis就能搜索到这个配置文件,然后编写一个初始化类:
public class SqlConfig {
private SqlConfig() {}
private static final SqlMapClient sqlMap;
static {
try {
java.io.Reader reader = Resources.getResourceAsReader ("sql-map-config.xml");
sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Error initializing SqlConfig. Cause: " + e);
}
}
public static SqlMapClient getSqlMapInstance () {
return sqlMap;
}
}

SqlMapClient封装了访问数据库的大部分操作,可以直接使用SqlConfig.getSqlMapInstance()获得这个唯一实例。

select [accountId] from [Account] where
[username] = #username# and password = #password#
</select>

articleDao.deleteArticle(articleId);
}
要分离用户验证逻辑,可以使用Proxy模式,或者使用Spring的AOP,利用MethodInterceptor实现,不过,由于逻辑很简单,完全可以直接写在一块,不必使用过于复杂的设计。
至此,我们的Blog已经实现了所有的后台业务逻辑,并且提供统一的Facade接口。前台Web层仅仅依赖这个Facade接口,这样,Web层和后台耦合非常松散,即使替换整个Web层也非常容易。


目前实现了两个Skin,出于简单起见,直接将路径硬编码在SkinManager中。

InputStream input = file.getInputStream();
// 写入文件...
}

pw.close();

测试

服务器配置为:P4 1.4G,512M DDR,100M Ethernet,Windows XP Professional SP1。
测试服务器分别为WebLogic Server 8.1,Tomcat 4.1/5.0,Resin 2.1.1。
测试数据库为MS SQL Server 2000 SP3。如果你使用Oracle或者DB2,MySQL等其他数据库并测试成功,请将SQL初始化脚本和详细配置过程发一份给我,谢谢。
由于时间有限,没有测试中文和作进一步的调优。WebLogic Server和iBatis有很多优化选项,详细配置可以参考相关文档。

总结

Spring的确是一个优秀的J2EE框架,通过Spring强大的集成能力,我们能轻松设计出灵活的多层J2EE应用而无需复杂的EJB组件支持。由于时间仓促,水平有限,文中难免有不少错误,恳请读者指正。

http://www.javasprite.com/crystal/blog-src.zip下载。

http://sourceforge.net/projects/rsslibj/下载。

参考

“Spring Reference”,Rod Johnson等。
“iBatis SQL Maps Guide”。
“Apache Ant 1.6.2 Manual”。
Springframework的JPetStore示例是非常棒的设计,本文参考了JPetStore的许多设计模式。

http://blog.csdn.net/asklxf/,欢迎访问。

相关文章:

  • 2021-08-02
  • 2021-08-25
  • 2021-07-20
  • 2021-11-30
  • 2021-12-17
  • 2021-05-29
  • 2021-08-10
  • 2022-03-14
猜你喜欢
  • 2021-08-15
  • 2022-12-23
  • 2022-01-06
  • 2021-11-13
  • 2021-11-16
  • 2021-05-10
  • 2021-04-12
相关资源
相似解决方案