分享
 
 
 

J2EE实战留言本(升级应用篇)

王朝java/jsp·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

前言

在上一篇实战EJB教程里,我们学写了一个CMP的实体Bean和sessionBean,sessionBean通过模型来操作实体Bean,基于Struts的jsp Framework 在javabean中访问EJB,得出最终结果在JSP视图层中显示,虽然简单,但这也是基本的流程!在完成这篇教程之后,我就在思量如何再写一个完整的应用,恰好论坛中的深空小妖写了一个基于php的留言本!于是我就想到也写一篇留言本的文章吧,留言本虽然很简单,但它却是一个基础,增加管理回复等就相当于一个小型的BBS,稍做修改也可以将它变成一个文章发布系统!

在我考虑之下,我决定写一个基于j2ee的留言本!

用于此次教学的就是留言本的tech版,它相当简单,只具有留言和查看的功能!但是对初学者来说这却是最好的入门捷径!

广告

在此tech版留言本的基础上我二次开发了它的商业版(数据库采用Oracle9i)!在完成我的tech版后,大家可以根据我下面的提示来定制自己的商业版!

1。商业版支持国际化功能,根据客户端IE语言自动切换相对应的语言信息资源,采用UTF-8的编码!

(利用struts的国际化功能)

2。完整的后台管理功能,以管理员登陆留言本后,可对留言进行删除,编辑,回复

(增加管理员权限的表,和实体BEAN)

3。LOG写日志功能

(利用log4J)

4。数据库转为xml文件导入导出

(看看JDOM,会有不小的收获)

5。上传下载功能

(jspsmartupload.jar)

6。留言查找功能

(我的方法是再写出一个搜索的sessionBean,当然也可以看看lUCene,一个开源的搜索引擎包)

7。个性化设置

(能完成以上的相信这个就不成问题)

本人已经注册了j2eestudio.com的域名,希望能与志同道合的朋友共同合作,请PM我!

PS又PS,如果有独立服务器的朋友帮忙最好!

相关知识

本篇立足于初学者,因此对一些相关概念的东西我会提一下,更具体的当然希望你在完成本教程后去Google上搜一下,这样印像更深刻!

J2EE:适用于创建服务器应用程序和服务的Java 2平台企业版(Java 2 Platform EnterPRise Edition,J2EE)

EJB:商业组件的部署环境,在EJB Server中提供了分布式计算环境中组件需要的所有服务,例如组件生命周期的管理、数据库连接的管理、分布式事务的支持、组件的命名服务等等。

Weblogic:BEA公司出品的J2ee平台应用服务器,全面支持J2EE标准,从6.0版开始率先支持EJB2.0规范,内置jdk为1.3.1版,虽然目前该产品已经出到了8.1,但我仍对小巧的6.1sp2版本情有独钟,基本上能满足我学习和工作的需要,不过它的软肋就是JDK的版本太低,虽然也可以自己将JDK的版本换成JDK1.4.X,但是或多或少会出现些问题,也因由此,我的struts一直使用的是1.1-b1版,因为在此后的正式版无法在weblogic6.1上运行!不得不说是遗憾!!

Struts:Struts是采用Java Servlet/JavaServer Pages技术,开发Web应用程序的开放源码的framework。Struts是apache.org开源组织Jakarta项目的一部分,在论坛中见到有人说它最终会被淘汰,其实鼓吹这种论点的早就见到过,Struts也许的确不算是最高效的JSP framework,学起来有些困难,但当你真正掌握,你才会发现它的灵活与强大,也甚至有人说SUN的JSP幸亏有struts这颗救命稻草,不然早就完了一说呢,不管怎么说,Struts已经有了相当广泛的商业应用,而且网上的资料也很多,希望大家认真学学,大家可以到官方网站上看看

jakarta.apache.org/struts

题外话:struts1.1允许多个控制文件,不像我们原来为了写一个控制文件经常check in/out啦!可我选择weblogic6.1就没法用struts1.1郁闷呀!

JSP:这个相信不用我说了吧,它可以像asp,PHP那种写法,将控制语句代码夹杂在Html代码中间,相对于比较复杂的JSP页面,比如JIVE论坛的JSP页面吧,你就会明白,看了就会犯晕,所以我们完全可以把控制语句交给struts来处理,这样我们在页面中看到的就是干净“代码”,更利于团体合作,发挥各人所才,程序员可以专心致志的写代码,而网页设计师则可以设计漂亮的页面!

相关工具

MySQL:今次学习版的数据库就用它了。

weblogic6.1sp2:我已经介绍N次了吧,呵呵,相关配置看看我以前的贴子。

Jbuilder7:EJB,JSP全在这里搞定啦!

Struts1.1-b1:去下载吧,不过我会提供一个经我修改支持中文的struts.jar

Struts console:写Struts-config.xml的好工具,真是太方便了

mysql.jar:提供连接mysql的JDBC驱动

平台搭建请参看我以前的相关贴子,一些工具包我会试着找空间下载的,OK,今天暂到这里,明天我们进入代码实战篇!有什么问题请进论坛PM我!

进入讨论组讨论。

代码实战篇

建立后台数据库

在最初的时候,我并没有打算用到数据库,我以XML为数据源,但遇到点麻烦,当初为了支持国际化的留言,必须使XML的编码使用UTF-8,但是在Struts中操作XML文件时,始终是以ANSI写入的,最后我引入了JDOM来操作写入XML文件,可以直接指定XML的编码格式获得成功,而且JDOM操作XML真的是相当方便,大家可以到它的官方网站去看看http://www.jdom.org。在完成之后,以我对XML有限的理解,我认为它作为数据信息描述、交换、存诸是强项,但真的把它用作数据服务在性能上也许是瓶颈,因为它在内存中不断增大,虽说手头上的资料有XML数据服务器一说,但没有进一步作研究,所以我改换MySQL做为数据库服务。MySql真的很小巧好用,不过我不知道如何在Mysql里更改数据库的编码,在Oracle里是可以直接指定数据库的默认编码,也就是我存入的UTF-8编码格式的信息在Oracle里可以正常显示,但在Mysql里就做不到了,它们都是“乱码",而且取出来也是乱码,我只有在数据库连接池里转码一次,使取出数据的都是正常的!不过此次TECH版不涉及国际化功能,不必伤此脑筋,让我们看看数据库表的设计吧!

像上次一样,我使用Navicat工具在Mysql中建立了guestbook的数据库,并且建立了留言所使用的book表.

接下来就是设计book表中的字段,下面是基本的信息,大家也可以根据自己的需要自行修改

id(留言自动编号,主键)

name(留言姓名,varchar,不允许为空)

email(留言者电邮,varchar,允许为空)

QQ(留言者QQ号码,varchar,允许为空)

posttime(留言提交时间,datetime,不允许为空)

comment(留言内容,varchar,不允许为空)

ip(留言者IP,varchar,不允许为空)

下面是我用Navicat导出的SQL脚本!

/*

MySQL Backup

Source Host: localhost

Source Server Version: 4.0.12-nt

Source Database: guestbook

Date: 2003-09-14 15:09:17

*/

use guestbook ;

#----------------------------

# Table structure for book

#----------------------------

create table book (

id int(11) not null auto_increment,

name varchar(100) not null,

email varchar(50),

qq varchar(50),

posttime datetime not null default '0000-00-00 00:00:00',

`comment` text not null,

ip varchar(50) not null,

primary key (id))

type=MyISAM;

#----------------------------

# No records for table book

#----------------------------

进入讨论组讨论。

创建实体Bean

和上篇实战EJB一样,我们在Jbuilder中先建立一个guestbook.jpx项目,然后再利用向导建立EJB名为book,接着我们需要建立它的数据源,也命名为book,当然你想取什么名字都行,不过以后在weblogic中的数据源配置要和这里写的一样,由于这些配置和上一篇相同,所以这里我都省去了,请大家仔细看上篇的贴子,有问题请PM我!

首先创建book表的CMP实体Bean文件,由于ID是在数据库中自动增加,在此我们可以将它删除,而指定name为主键,同时我们修改posttime的类型为java.lang.String.

点击查看大图

接下来我们设计模型,这里放在value中,下面是BookValue.java的源代码

package guestbook.maxuan.ejb.entity.value;

import java.io.*;

public class BookValue implements Serializable{

public java.lang.String name;

public java.lang.String email;

public java.lang.String qq;

public java.lang.String posttime;

public java.lang.String comment;

public java.lang.String ip;

public java.lang.String action;

private void writeObject(ObjectOutputStream oos)

throws IOException {

oos.defaultWriteObject();

}

private void readObject(ObjectInputStream ois)

throws ClassNotFoundException,

IOException {

ois.defaultReadObject();

}

public String getAction() {

return action;

}

public void setAction(String action) {

this.action = action;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getEmail() {

return email;

}

public void setEmail(String email) {

this.email = email;

}

public String getQq() {

return qq;

}

public void setQq(String qq) {

this.qq = qq;

}

public java.lang.String getPosttime() {

return posttime;

}

public void setPosttime(java.lang.String posttime) {

this.posttime = posttime;

}

public String getIp() {

return ip;

}

public void setIp(String ip) {

this.ip = ip;

}

public String getComment() {

return comment;

}

public void setComment(String comment) {

this.comment = comment;

}

}

book.java的源代码

package guestbook.maxuan.ejb.entity;

import javax.ejb.*;

import java.util.*;

import guestbook.maxuan.ejb.entity.value.*;

public interface Book extends javax.ejb.EJBLocalObject {

public void setName(String name);

public String getName();

public void setEmail(String email);

public String getEmail();

public void setQq(String qq);

public String getQq();

public void setPosttime(String posttime);

public String getPosttime();

public void setComment(String comment);

public String getComment();

public void setIp(String ip);

public String getIp();

public BookValue getValue();

public void setValue(BookValue value);

}

BookBean.java的源代码

package guestbook.maxuan.ejb.entity;

import javax.ejb.*;

import guestbook.maxuan.ejb.entity.value.*;

abstract public class BookBean implements EntityBean {

EntityContext entityContext;

public java.lang.String ejbCreate(java.lang.String name)

throws CreateException {

setName(name);

return null;

}

public java.lang.String ejbCreate(BookValue value)

throws CreateException {

setValue(value);

return null;

}

public void ejbPostCreate(java.lang.String name)

throws CreateException {

/**@todo Complete this method*/

}

public void ejbPostCreate(BookValue value)

throws CreateException {

}

public void ejbRemove() throws RemoveException {

/**@todo Complete this method*/

}

public abstract void setName(java.lang.String name);

public abstract void setEmail(java.lang.String email);

public abstract void setQq(java.lang.String qq);

public abstract void setPosttime(java.lang.String posttime);

public abstract void setComment(java.lang.String comment);

public abstract void setIp(java.lang.String ip);

public abstract java.lang.String getName();

public abstract java.lang.String getEmail();

public abstract java.lang.String getQq();

public abstract java.lang.String getPosttime();

public abstract java.lang.String getComment();

public abstract java.lang.String getIp();

public void ejbLoad() {

/**@todo Complete this method*/

}

public void ejbStore() {

/**@todo Complete this method*/

}

public void ejbActivate() {

/**@todo Complete this method*/

}

public void ejbPassivate() {

/**@todo Complete this method*/

}

public void unsetEntityContext() {

this.entityContext = null;

}

public void setEntityContext(EntityContext entityContext) {

this.entityContext = entityContext;

}

public BookValue getValue(){

BookValue value = new BookValue();

value.setName(getName());

value.setEmail(getEmail());

value.setQq(getQq());

value.setPosttime(getPosttime());

value.setComment(getComment());

value.setIp(getIp());

return value;

}

public void setValue(BookValue value){

setName(value.getName());

setEmail(value.getEmail());

setQq(value.getQq());

setPosttime(value.getPosttime());

setComment(value.getComment());

setIp(value.getIp());

}

}

BookHome.java的源代码

package guestbook.maxuan.ejb.entity;

import javax.ejb.*;

import java.util.*;

import guestbook.maxuan.ejb.entity.value.*;

public interface BookHome extends javax.ejb.EJBLocalHome {

public Book create(String name) throws CreateException;

public Book create(BookValue value) throws CreateException;

public Collection findAll() throws FinderException;

public Book findByPrimaryKey(String name)

throws FinderException;

}

记得要写findall的Query语句:SELECT OBJECT(o) FROM Book AS o

接下来我们设计模型,这里放在value中,下面是BookValue.java的源代码

<textarea columns=100 rows=50>

package guestbook.maxuan.ejb.entity.value;

import java.io.*;

public class BookValue implements Serializable{

public java.lang.String name;

public java.lang.String email;

public java.lang.String qq;

public java.lang.String posttime;

public java.lang.String comment;

public java.lang.String ip;

public java.lang.String action;

private void writeObject(ObjectOutputStream oos)

throws IOException {

oos.defaultWriteObject();

}

private void readObject(ObjectInputStream ois)

throws ClassNotFoundException,

IOException {

ois.defaultReadObject();

}

public String getAction() {

return action;

}

public void setAction(String action) {

this.action = action;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getEmail() {

return email;

}

public void setEmail(String email) {

this.email = email;

}

public String getQq() {

return qq;

}

public void setQq(String qq) {

this.qq = qq;

}

public java.lang.String getPosttime() {

return posttime;

}

public void setPosttime(java.lang.String posttime) {

this.posttime = posttime;

}

public String getIp() {

return ip;

}

public void setIp(String ip) {

this.ip = ip;

}

public String getComment() {

return comment;

}

public void setComment(String comment) {

this.comment = comment;

}

}

</textarea>

book.java的源代码

<textarea columns=100 rows=50>

package guestbook.maxuan.ejb.entity;

import javax.ejb.*;

import java.util.*;

import guestbook.maxuan.ejb.entity.value.*;

public interface Book extends javax.ejb.EJBLocalObject {

public void setName(String name);

public String getName();

public void setEmail(String email);

public String getEmail();

public void setQq(String qq);

public String getQq();

public void setPosttime(String posttime);

public String getPosttime();

public void setComment(String comment);

public String getComment();

public void setIp(String ip);

public String getIp();

public BookValue getValue();

public void setValue(BookValue value);

}

</textarea>

BookBean.java的源代码

<textarea columns=100 rows=50>

package guestbook.maxuan.ejb.entity;

import javax.ejb.*;

import guestbook.maxuan.ejb.entity.value.*;

abstract public class BookBean implements EntityBean {

EntityContext entityContext;

public java.lang.String ejbCreate(java.lang.String name)

throws CreateException {

setName(name);

return null;

}

public java.lang.String ejbCreate(BookValue value)

throws CreateException {

setValue(value);

return null;

}

public void ejbPostCreate(java.lang.String name)

throws CreateException {

/**@todo Complete this method*/

}

public void ejbPostCreate(BookValue value)

throws CreateException {

}

public void ejbRemove() throws RemoveException {

/**@todo Complete this method*/

}

public abstract void setName(java.lang.String name);

public abstract void setEmail(java.lang.String email);

public abstract void setQq(java.lang.String qq);

public abstract void setPosttime(java.lang.String posttime);

public abstract void setComment(java.lang.String comment);

public abstract void setIp(java.lang.String ip);

public abstract java.lang.String getName();

public abstract java.lang.String getEmail();

public abstract java.lang.String getQq();

public abstract java.lang.String getPosttime();

public abstract java.lang.String getComment();

public abstract java.lang.String getIp();

public void ejbLoad() {

/**@todo Complete this method*/

}

public void ejbStore() {

/**@todo Complete this method*/

}

public void ejbActivate() {

/**@todo Complete this method*/

}

public void ejbPassivate() {

/**@todo Complete this method*/

}

public void unsetEntityContext() {

this.entityContext = null;

}

public void setEntityContext(EntityContext entityContext) {

this.entityContext = entityContext;

}

public BookValue getValue(){

BookValue value = new BookValue();

value.setName(getName());

value.setEmail(getEmail());

value.setQq(getQq());

value.setPosttime(getPosttime());

value.setComment(getComment());

value.setIp(getIp());

return value;

}

public void setValue(BookValue value){

setName(value.getName());

setEmail(value.getEmail());

setQq(value.getQq());

setPosttime(value.getPosttime());

setComment(value.getComment());

setIp(value.getIp());

}

}

</textarea>

BookHome.java的源代码

<textarea columns=100 rows=50>

package guestbook.maxuan.ejb.entity;

import javax.ejb.*;

import java.util.*;

import guestbook.maxuan.ejb.entity.value.*;

public interface BookHome extends javax.ejb.EJBLocalHome {

public Book create(String name) throws CreateException;

public Book create(BookValue value) throws CreateException;

public Collection findAll() throws FinderException;

public Book findByPrimaryKey(String name)

throws FinderException;

}

</textarea>

记得要写findall的Query语句:SELECT OBJECT(o) FROM Book AS o

进入讨论组讨论。

创建sessionBean

在昨天,我们完成了实体Bean,它实际上是映射到数据库行并为行的每个列定义了getter和setter方法,今天我们来完成sessionBean。

BookControl.java的源代码

package guestbook.maxuan.ejb.control;

import javax.ejb.*;

import java.util.*;

import java.rmi.*;

import guestbook.maxuan.ejb.entity.value.*;

public interface BookControl extends javax.ejb.EJBObject {

public void savely(BookValue value) throws RemoteException;

public ArrayList getLyList() throws RemoteException;

}

BookControlBean的源代码

package guestbook.maxuan.ejb.control;

import javax.ejb.*;

import java.util.*;

import guestbook.maxuan.ejb.entity.*;

import guestbook.maxuan.ejb.entity.value.*;

public class BookControlBean implements SessionBean {

SessionContext sessionContext;

public void ejbCreate() throws CreateException {

/**@todo Complete this method*/

}

public void ejbRemove() {

/**@todo Complete this method*/

}

public void ejbActivate() {

/**@todo Complete this method*/

}

public void ejbPassivate() {

/**@todo Complete this method*/

}

public void setSessionContext(SessionContext sessionContext) {

this.sessionContext = sessionContext;

}

public void savely(BookValue value) {

Book book=null;

try {

javax.naming.Context context =

new javax.naming.InitialContext();

BookHome bookHome= (BookHome)context.lookup("Book");

if(value.getAction().equals("add")){

book=bookHome.create(value);

}else{

try{

book=bookHome.findByPrimaryKey(value.getName());

book.setValue(value);

}catch(FinderException fe){

}

}

}catch (Exception ex) {

throw new EJBException(ex);

}

}

public ArrayList getLyList(){

ArrayList LyList=new ArrayList();

try {

javax.naming.Context context = new

javax.naming.InitialContext();

BookHome bookHome= (BookHome)context.lookup("Book");

Collection lyCntl = bookHome.findAll();

Iterator iterator = lyCntl.iterator();

while(iterator.hasNext()){

Book book = (Book) iterator.next();

LyList.add(book.getValue());

}

}catch (Exception ex) {

throw new EJBException(ex);

}

return LyList;

}

}

BookControlHome的源代码

package guestbook.maxuan.ejb.control;

import javax.ejb.*;

import java.util.*;

import java.rmi.*;

public interface BookControlHome extends javax.ejb.EJBHome {

public BookControl create() throws CreateException,

RemoteException;

}

这样我们就完成了sessionBean的编写,它操作实体Bean赋于value的值,

这里比上次的教程多了写入的操作!

进入讨论组讨论。

struts部份

首先,请大家下载jakarta-struts-1.1-b1.zip,直接在google里键入搜索即可,此版本可应用布署在weblogic6.1中。记得顺便把jakarta-struts-1.1-b1-src.zip也下了,这是它的源码文件,方便我们修改!!

打开jakarta-struts-1.1-b1.zip这个压缩包文件,INSTALL、LICENSE、README三个文件不用说了自己看,lib文件夹中就是所需要的库文件和标签文件,webapps中有几个示例文件,struts-documentation.war可装配到weblogic中,一定要看看,详尽的文档!

首先,我们要在JBuilder中定义struts库文件的位置,点击TOOLS菜单在下拉中选中Configure Libraries,在弹出的窗口中新定义一个LIB,我们取名为struts 1.1-b1,定义到Project中,当然为了以后方便,你可以指定为User home!

这里我是把jakarta-struts-1.1-b1.zip文件夹直接解压到应用目录guestbook的lib中,将struts包中所有的*.jar文件选中加入,然后点OK即完成了struts 1.1-b1库文件的定义!

然后我们需要指定在此次guestbook的项目应用中引入struts 1.1-b1,在打开guestbook.jpx后,在Project菜单中下拉选中Project Properties,在弹出的窗口中,在下面点击Required Libraries,出现画面如下图所示:

点右边的ADD,将刚才我们定义的struts 1.1-b1库文件加入,如下图

完成后如下图所示:

以上部分,我们完成了Struts1.1-b1在此次教程应用中的配置!

进入讨论组讨论。

有了Struts资源的调用,我们继续来完成JAVABEAN部分的编写!

首先,我们编写PAction.java文件来完成连接等初始化工作,源代码如下:

PAcation.java的源代码

package guestbook.maxuan.action;

import javax.naming.*;

import java.util.Properties;

import java.util.*;

import javax.rmi.PortableRemoteObject;

import java.io.IOException;

import java.lang.reflect.InvocationTargetException;

import java.util.Locale;

import java.util.Vector;

import javax.servlet.RequestDispatcher;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.PropertyUtils;

import org.apache.struts.action.ActionError;

import org.apache.struts.action.ActionErrors;

import org.apache.struts.action.Action;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

import org.apache.struts.action.ActionServlet;

import org.apache.struts.util.MessageResources;

import guestbook.maxuan.ejb.control.*;

public class PAction extends Action{

//public ActionErrors errors = new ActionErrors();

public BookControl control = null;

public Context getInitialContext() {

String url = "t3://127.0.0.1:";

String user = null;

String passWord = null;

Properties properties = null;

ActionServlet actionServlet = this.getServlet();

String port = actionServlet.getServletConfig().

getInitParameter("port");

url = url + port;

try {

properties = new Properties();

properties.put(Context.INITIAL_CONTEXT_FACTORY,

"weblogic.jndi.WLInitialContextFactory");

properties.put(Context.PROVIDER_URL, url);

if (user != null) {

properties.put(Context.SECURITY_PRINCIPAL, user);

properties.put(Context.SECURITY_CREDENTIALS,

password == null ? "" : password);

}

return new InitialContext(properties);

}

catch(Exception e) {

e.printStackTrace();

}

return null;

}

public BookControl getInitControl( ){

BookControl control = null;

Context ctx = getInitialContext();

try{

Object object = ctx.lookup("BookControl");

BookControlHome bookcHome =

(BookControlHome) PortableRemoteObject.narrow(object,

BookControlHome.class);

control = bookcHome.create();

}catch(Exception e){

e.printStackTrace();

}

return control;

}

}

接着我们编写LyListAction.java文件,得到所有的留言信息LIST。

LyListAction.java的源代码

package guestbook.maxuan.action;

import javax.naming.*;

import java.util.Properties;

import javax.rmi.PortableRemoteObject;

import java.util.*;

import java.util.Locale;

import javax.servlet.RequestDispatcher;

import javax.servlet.ServletException;

import javax.servlet.ServletConfig;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionMapping;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ForwardingActionForward;

import org.apache.struts.action.ActionServlet;

import org.apache.struts.util.MessageResources;

import guestbook.maxuan.ejb.control.*;

public class LyListAction extends PAction{

public ActionForward perform(ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response) {

Locale locale = getLocale(request);

HttpSession session = request.getSession();

Context ctx = (Context)session.getAttribute("ctx");

if(ctx==null){

ctx = getInitialContext();

session.setAttribute("ctx",ctx);

}

try{

Object object = ctx.lookup("BookControl");

BookControlHome bookHome =

(BookControlHome) PortableRemoteObject.narrow(object,

BookControlHome.class);

BookControl bookControl = bookHome.create();

ArrayList lyList = bookControl.getLyList();

session.setAttribute("lyList",lyList);

}catch(Exception e){

e.printStackTrace();

}

return (mapping.findForward("success"));

}

}

由于我们需要新加留言,所以这次比上次的EJB教程多出了存储部份,留言需要一个FORM来提交,最后进行

存储,所以我们需要新加入LyForm.java、LyEditAction.java、LySaveAction.java三个文件的编写,源代

码如下:

LyForm.java的源代码

package guestbook.maxuan.action;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionError;

import org.apache.struts.action.ActionErrors;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionMapping;

import guestbook.maxuan.ejb.entity.value.*;

public final class LyForm extends ActionForm{

public String action="add";

public String name;

public String email;

public String qq;

public String comment;

private BookValue value = new BookValue();

public String getAction() {

return action;

}

public void setAction(String action) {

this.action = action;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getEmail() {

return email;

}

public void setEmail(String email) {

this.email = email;

}

public String getQq() {

return qq;

}

public void setQq(String qq) {

this.qq = qq;

}

public String getComment() {

return comment;

}

public void setComment(String comment) {

this.comment = comment;

}

public BookValue getValue(){

value.setName(name);

value.setEmail(email);

value.setQq(qq);

value.setComment(comment);

value.setAction(action);

return value;

}

public void setValue(BookValue value){

name = value.getName();

email = value.getEmail();

qq = value.getQq();

comment = value.getComment();

action = value.getAction();

}

}

LyEditAction.java的源代码

package guestbook.maxuan.action;

import javax.naming.*;

import java.util.Properties;

import java.util.*;

import javax.rmi.PortableRemoteObject;

import java.io.IOException;

import java.lang.reflect.InvocationTargetException;

import java.util.Locale;

import java.util.Vector;

import javax.servlet.RequestDispatcher;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.PropertyUtils;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.apache.struts.action.Action;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

import org.apache.struts.action.ActionServlet;

import org.apache.struts.util.MessageResources;

import guestbook.maxuan.action.PAction;

import guestbook.maxuan.ejb.entity.value.*;

import guestbook.maxuan.ejb.entity.*;

import guestbook.maxuan.ejb.control.*;

import java.util.Collection;

public class LyEditAction extends PAction{

public ActionForward execute(ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response)

throws Exception {

Locale locale = getLocale(request);

MessageResources messages = getResources(request);

HttpSession session = request.getSession();

String action = request.getParameter("action");

Context ctx = (Context)session.getAttribute("ctx");

BookValue value =(BookValue) request.getAttribute("value");

//errors.clear();

if (form == null) {

form = new LyForm();

if ("request".equals(mapping.getScope())) {

request.setAttribute(mapping.getAttribute(), form);

} else {

session.setAttribute(mapping.getAttribute(), form);

}

}

if(ctx==null){

ctx = getInitialContext();

session.setAttribute("ctx",ctx);

}

LyForm lyForm = (LyForm) form;

if(action!=null){

lyForm.setAction(action);

}

if (value!=null){

try {

PropertyUtils.copyProperties(lyForm, value);

} catch (Exception e) {

}

}

return (mapping.findForward("success"));

}

}

LySaveAction.java的源代码

package guestbook.maxuan.action;

import javax.naming.*;

import java.util.Properties;

import java.util.*;

import java.text.*;

import javax.rmi.PortableRemoteObject;

import java.io.IOException;

import java.lang.reflect.InvocationTargetException;

import java.util.Locale;

import java.util.Vector;

import javax.servlet.RequestDispatcher;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.PropertyUtils;

import org.apache.struts.action.ActionError;

import org.apache.struts.action.ActionErrors;

import org.apache.struts.action.Action;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

import org.apache.struts.action.ActionServlet;

import org.apache.struts.util.MessageResources;

import guestbook.maxuan.action.PAction;

import guestbook.maxuan.ejb.entity.value.*;

import guestbook.maxuan.ejb.entity.*;

import guestbook.maxuan.ejb.control.*;

import java.sql.*;

public final class LySaveAction extends PAction{

public ActionForward execute(ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response)

throws Exception {

Locale locale = getLocale(request);

MessageResources messages = getResources(request);

HttpSession session = request.getSession();

BookValue value=null;

LyForm lyForm = (LyForm) form;

Context ctx = (Context)session.getAttribute("ctx");

//errors.clear();

if(control==null){

control=getInitControl();

session.setAttribute("control",control);

}

//errors = lyForm.check();

try {

Calendar cal = Calendar.getInstance();

SimpleDateFormat formatter=

new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置留言时间格式

String datestr = formatter.format

(new Timestamp(cal.getTime().getTime()));

value = lyForm.getValue();

value.setIp(request.getRemoteAddr());//写入访问者IP

value.setPosttime(datestr);

control.savely(value);

}catch(Exception e){

e.printStackTrace();

}

return (mapping.findForward("success"));

}

}

在上面,我将原本写在里面的检查语句都注释掉了,大家可以自己写进去,也就是对邮件,留言不能为空等检查,当然也可以在页面中写Javascript小脚本,不过这对有心恶意捣乱的人没什么用!

PAction.java完成一些连接等初始动作,其它的分别为显示留言,提交留言等动作,也可以自行定义添加其它动作在里面!例如删除!进入讨论组讨论。

JSP部份

JSP在本篇教程应用中作为视图层,在它里面,你看不到传统的<% %>包含的控制语句,取而代之的是Struts的标签控制!

首先,我们需要在guestbook.jpx的应用中建立web application应用,命名为guestbook,点开它下面的Deployment descriptors,我们会看到web.xml和weblogic.xml两个文件,它们都是建立web application后自动产生的(当你配置的项目应用服务为weblogic时,才会生成weblogic.xml文件,具体配置请见拙作一)

现在我们双击weblogic.xml文件来编辑它,这里我们主要是能让它支持中文!

weblogic.xml源代码

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

<!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems,

Inc.//DTD Web Application 6.1//EN"

"http://www.bea.com/servers/wls610/dtd/weblogic-web-jar.dtd">

<weblogic-web-app>

<jsp-descriptor>

<jsp-param>

<param-name>encoding</param-name>

<param-value>GBK</param-value>

</jsp-param>

</jsp-descriptor>

</weblogic-web-app>

接着我们需要编辑web.xml文件,主要是配置默认的首页文件,Servlets和Tag Libraries。你可以在WebApp DD Editor项目中配置,也可以直接在Source面板中直接编写源代码

web.xml源代码

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

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems,

Inc.//DTD Web Application 2.3//EN"

"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<servlet>

<servlet-name>action</servlet-name>

<servlet-class>org.apache.struts.action.ActionServlet

</servlet-class>

<init-param>

<param-name>config</param-name>

<param-value>/WEB-INF/struts-config.xml</param-value>

</init-param>

<init-param>

<param-name>debug</param-name>

<param-value>2</param-value>

</init-param>

<init-param>

<param-name>detail</param-name>

<param-value>2</param-value>

</init-param>

<init-param>

<param-name>port</param-name>

<param-value>7001</param-value>

</init-param>

<load-on-startup>2</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>action</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

<welcome-file-list>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

<taglib>

<taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>

<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>

</taglib>

<taglib>

<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>

<taglib-location>/WEB-INF/struts-html.tld</taglib-location>

</taglib>

<taglib>

<taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>

<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>

</taglib>

</web-app>

在完成以上两个文件的编写后,我们把struts1.1-b1中的所有控制标签文件(除*.jar外的所有文件)拷贝到留言本的应用目录WEB-INF目录中(当你在JBuilder的项目应用中建立web application时,它就会自己帮你建立WEB-INF),如果你以目录形式来发布此次应用,你必须手动在WEB-INF目录下建立一个lib目录,将所有需要的LIB资源文件拷进去,当然如果你在JBuilder中编译此web application它除了会自动将WEB应用打包为guestbook.war文件外,还会自动在WEB-INF中建立LIB文件夹,并将相关的LIB资源文件拷进去!

进入讨论组讨论。

接着我们需要建立struts-config.xml文件,它是配置struts控制的重要文件,编写Struts-config.xml的利器非Struts Console不可,下边是详细的图解:

首先我们新建一个struts config文件,我们选用Struts1.1 Config File,点OK

点击Form Beans新建一个lyForm,NAME:lyForm,Type:guestbook.maxuan.action.LyForm

然后我们在Action Mappings分别加入lyList、saveLy、editLy三个Action!

lyList Action主要是列出所有的留言信息,在path填入/lyList,Type对应它在JAVABEAN中的文件guestbook.maxuan.action.LyListAction(写出完整的文件信息位置),在Forwards加入success,指向正确的JSP文件,这里命名为indexCnt.jsp,我们追溯到/lyList对应的LyListAction.java文件,在最后我们看到的"return (mapping.findForward("success"));"即与此处的success命名对应,也就是成功后即指向success,

而在Struts-config.xml释诠了success指向的实际JSP文件是indexCnt.jsp文件!

按以上方式我们继续编辑saveLy、editLy,图示如下:

saveLy、editLy相对应的是FORM Beans,所以我们必须在它们的Form Bean中指定

在完成后,我们再看Form Beans中的lyForm的Referencing Actions就会看到path中已经有了/saveLy和/editLy

最后,我们需要编辑信息资源项目,在Message Resources下新加入New Message Resource,parameter为ApplicationResources,Messages Key为org.apache.struts.action.MESSAGE!

进入讨论组讨论。

由于在此篇教程中并没有涉及到国际化应用,应此我们并没有编写相应的资源文件!

struts-config.xml的源代码

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

<!DOCTYPE struts-config PUBLIC "-//

Apache Software Foundation//DTD Struts Configuration 1.1//EN"

"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>

<form-beans>

<form-bean name="lyForm" type="guestbook.maxuan.action.LyForm" />

</form-beans>

<action-mappings>

<action path="/lyList"

type="guestbook.maxuan.action.LyListAction">

<forward name="success" path="/indexCnt.jsp" redirect="false" />

</action>

<action path="/saveLy" type="guestbook.maxuan.action.LySaveAction"

name="lyForm" input="/ly.jsp"

scope="request">

<forward name="success" path="/index.jsp" redirect="true" />

</action>

<action path="/editLy" type="guestbook.maxuan.action.LyEditAction"

name="lyForm" scope="request">

<forward name="success" path="/ly.jsp" redirect="false" />

</action>

</action-mappings>

<message-resources parameter="ApplicationResources"

key="org.apache.struts.action.MESSAGE" />

</struts-config>

以上,我们完成了此次教程应用的struts-config.xml的编写,我们看到使用struts console工具编写Struts-config.xml是多么的轻松容易,如果用纯文本编辑工具来写一个大型的struts配置文件,我想恐怕是一个噩梦!

在完成了配置后,我们开始写JSP页面,首先我们定义template,它是struts的模板,所有相同的部份都可以使用template!

template.jsp的源代码

<%@ taglib uri='/WEB-INF/struts-template.tld' prefix='template' %>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=GBK">

<title>留言本教程范例</title>

</head>

<body bgcolor="#ffffff" leftmargin="0" topmargin="0"

marginwidth="0" marginheight="0">

<template:get name='header'/>

<template:get name='content'/>

<template:get name='footer'/>

</body>

</html>

接着完成首页index.jsp文件,它的模板使用template.jsp,定义了页首(header.htm),页尾(footer.htm),及内容显示(由/lyList.do映射到indexCnt.jsp)

index.jsp的源代码

<%@ taglib uri='/WEB-INF/struts-template.tld' prefix='template' %>

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

<template:insert template='/template.jsp'>

<template:put name='header' content='/header.htm'/>

<template:put name='content' content='/lyList.do'/>

<template:put name='footer' content='/footer.htm'/>

</template:insert>

页首header.htm的代码(由于只是教程,我并没有进行页面美化工作,大家可以根据自己的喜爱自定义)

<table width="90%" height="50" border="0" align="center"

cellpadding="0" cellspacing="0">

<tr>

<td align="center"><strong>留 言 本</strong></td>

</tr>

</table>

页尾footer.htm的源代码

<table width="90%" border="0" align="center" cellpadding="0"

cellspacing="0">

<tr>

<td align="center">留言本教程范例 2003-9-21</td>

</tr>

</table>

留言内容显示indexCnt.jsp的源代码

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>

<jsp:useBean id="lyList" scope="session"

type="java.util.ArrayList"/>

<table width="90%" border="0" align="center" cellpadding="0"

cellspacing="0">

<tr>

<td align="right"><html:link page="/editLy.do?action=Add">我要

留言</html:link> </td>

</tr>

</table>

<logic:iterate id="value" name="lyList"

type="guestbook.maxuan.ejb.entity.value.BookValue"

indexId="index">

<table width="90%" border="0" align="center"

cellpadding="5" cellspacing="2">

<tr>

<td><font size="4"><b><bean:write

name="value" property="name"/></b></font><br>

Email:<a href='mailto:<bean:write

name="value" property="email"/>'><bean:write name="value"

property="email"/></a>

QQ:<bean:write name="value" property="qq"/> <br>

留言时间:<bean:write name="value"

property="posttime"/><br><br>

<bean:write name="value" property="comment"/></td>

</tr>

<tr>

<td height="1"><hr size="1" noshade></td>

</tr>

</table>

</logic:iterate>

留言输入页面ly.jsp的源代码

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>

<html>

<head>

<title>留言</title>

<meta http-equiv="Content-Type"

content="text/html; charset=gb2312">

</head>

<body>

<table width="70%" border="1" align="center" cellpadding="2"

cellspacing="2"

bordercolor="#000000">

<html:form action="/saveLy">

<tr>

<td width="21%" height="20">姓名</td>

<td width="79%" height="20"><html:text property="name"

size="20"/></td>

</tr>

<tr>

<td height="20">email</td>

<td height="20"><html:text property="email" size="20"/></td>

</tr>

<tr>

<td height="20">qq</td>

<td height="20"><html:text property="qq" size="20"/></td>

</tr>

<tr>

<td height="20">留言内容</td>

<td height="20"><html:textarea property="comment" rows="5"

cols="50"/></td>

</tr>

<tr align="center">

<td height="20" colspan="2"><html:submit>保存</html:submit>

<html:reset>重置</html:reset></td>

</tr>

</html:form>

</table>

</body>

</html>

最后效果如图:

此时我们的j2ee体系的留言本教程也就告于段落!

从这篇教程我们可以窥见j2ee多层体系结构的端倪,

本篇教程只是一个基石,在此之上,你可以灵活地搭建更大型的应用,

这才是我写此文的最终目的!

后记:幻想曲花了30多分钟的时间从经典论坛中将maxuan9的帖子整理到了文档区,

希望对那些想学J2EE和正在学J2EE的朋友一点启示、一点帮助!

进入讨论组讨论。

补遗篇

在完成之后,我想我有几个地方得交待一下!

1.留言排序的问题

按照上面的教程完成之后,我们发现最新的留言总在后面,而不是最上方,这是因为我们没有进行排序(我们将信息加入LyList中,它的顺序总是add(),最后加入的总排在最后面,而logic:iterator标签都是从索引0开始显示到最末,因此我们必须要对此LyList进行排序)

从BookControlBean.java中可以看出,我们使用ejbFinder得到Collection,ArrayList类接受Collection对象构造函数,使Collection转换为了List。因此我们可以相当简单的使用Collections.sort()、Collections.reverse()进行排序!

PS:最后一幅完成图即为排序后的页面!

2.留言本页面中文的显示问题

在前面我们说过为了直接在页面上输入中文,我们必须对struts.jar包进行一下改装

具体的文件为:PropertyMessageResources.java

将第289行的:messages.put(messageKey(localeKey, key),props.getProperty(key));

改成下面的代码:

String sProps = props.getProperty(key);

try

{

sProps = new String(sProps.getBytes("ISO-8859-1"),"GBK");

}

catch (Exception e)

{

e.printStackTrace();

}

messages.put(messageKey(localeKey, key),sProps);

然后重新编译生成新包。

为了方便大家,这里我直接提供新包下载

3.留言分页问题

在此教程中我并没有写分页,其实写分页相当简单,看看文档中的logic:iterator,提示:length和offset,发挥一下想像就能写出来!呵呵,自己慢慢进级吧,自己独立解决才是真正的乐趣所在!

至此,如果您对此教程还有什么疑问的话请PM我!!

拷贝代码的话可以去下面这个地址:

实战留言簿(EJB,Struts应用篇)

[全文完]

进入讨论组讨论。

(出处:http://www.knowsky.com)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有