返回列表 回复 发帖

体会真正的Struts开发, 比较详细

所谓Struts开发不是单纯的利用Action,ActionForm,ActionForward等等组件进行逻辑封装,而是更应该像在EJB这种架构进行的从整体到模块的设计。所以我认为Struts开发就应该建立在轻型EJB架构上的开发。
所以真正的Struts开发就是结合Hibernate这种底层数据库持久化,结合专业的日志系统Log4J,包含真正EJB异常处理模式的开发。
下面就是真正Struts开发里面必须涉及到的模块:
Struts 1.1
Hibernate 2.1
Log4J
JUnit
Cactus
JMeter
合适的Cache
合适的ConnectionPooler
合适的ThreadPooler
在界面设计上为了做到完全的统一建议使用Tiles标签,这是Struts1.1里面新加的。

下面我们以实例演示如何进行规范的Struts开发。(以工程开发性质讲解)

环境配置:
Eclipse3 M7
Tomcat 4.1+Eclipse的插件
MyEclipse for M7
MySQL4

这是开发之前必须准备的。

下面我们来重新规划上一期XXXX系统的开发,暂时命名为MyWeb
Web文件夹分配
Src Java源文件
Web 站点全部文件
Lib 编译用到的库
Test 测试文件夹
Doc 文档
TestSrc 进行尝试性的Java源文件
Resource 资源文件
Test\TestData 测试数据
Test\UnitTest JUnit单元测试
Test\WebTest cactus和jmeter实现web测试Jmeter对web应用层面和进行压力测试

为了方便期间,我们将Tomcat改为监视80端口而不再是8080了。修改Tomcat目录下的Server.Xml.
<Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
port="8080" minProcessors="5" maxProcessors="75"
enableLookups="true" redirectPort="8443"
acceptCount="100" debug="0" connectionTimeout="20000"
useURIValidationHack="false" disableUploadTimeout="true" />
将8080改为80
配置Eclipse
1. 先配置Tomcat插件
2. 配置MyEclipse
完成配置 22:00,半小时搞定
创建工程:
建立我们的目录
将一些文件夹设为Source文件夹
搞定2 现在22:09
设置工程为Tomcat工程
注意必须像上图一样填写
加入对Struts1.1支持
建立Tomcat工作目录
设置完整图如下:
OK,现在可以进行一般Struts开发调试了
下面加入对Hibernate的支持
下面配置Hibernate的数据库驱动
下面配置Hibernate的数据库驱动
在Hibernate目录下的hibernate.properties
我们配置MySQL

我们配置一下Log4J,拷贝就行了


这个Log4j.xml作用是在当前目录记录Error与Log信息
上一篇讲到测试Hibernate操作数据库,今天我们来利用Struts与Hibernate作一个Web实例。

我们第一步开始配置Tomcat的连接池
首先我们将MySQL的JDBC驱动拷贝到${TOMCAT_HOME}\common\lib下面,更改MyWeb设置如下
<Context path="/MyWeb" reloadable="true" docBase="E:\DEV\MyWeb\web"
workDir="E:\DEV\MyWeb\work\org\apache\jsp" >
<!--
设置连接池的JNDI名
-->
<Resource name="jdbc/mysql" auth="Container"
type="javax.sql.DataSource"/>
<ResourceParams name="jdbc/mysql">
<!--
工厂类
-->
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<!--
连接池基本设置
-->
<parameter>
<name>maxActive</name>
<value>100</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>30</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>10000</value>
</parameter>
<parameter>
<name>username</name>
<value>root</value>
</parameter>
<parameter>
<name>password</name>
<value></value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>com.mysql.jdbc.Driver</value>
</parameter>
<!--
数据库地址
-->
<parameter>
<name>url</name>
<value>jdbc:mysql://localhost/test?useUnicode=true</value>
</parameter>
</ResourceParams>
</Context>

设置好连接池,我们对连接池进行测试
我们编写一个Servlet测试在Servlet使用连接池
代码如下

package com.test.web;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.sql.DataSource;

import org.apache.log4j.Logger;
/**
* @author yanghx
* To change the template for this generated type comment go to Window -
* Preferences - Java - Code Generation - Code and Comments
*/
public class TestServlet extends HttpServlet {
private static Logger log = Logger.getLogger(TestServlet.class);

public void init() throws ServletException {
super.init();
String jndiName = "java:comp/env/jdbc/mysql";
try {
Context ctx = new InitialContext();
if (ctx == null) {
log.error("找不到上下文");
throw new Exception("找不到上下文");
}
DataSource ds = (DataSource) ctx.lookup(jndiName);
Connection conn = ds.getConnection();
PreparedStatement psmt = conn
.prepareStatement("select * from tbl_testhbm");
ResultSet rs = psmt.executeQuery();
log.info("连接池OK");
rs.close();
} catch (NamingException e) {
log.error("找不到上下文" + e.getMessage());
} catch (Exception e) {
log.error("出现错误" + e.getMessage());
}
}
}
配置Web.xml使这个Servlet在启动时加载。
<servlet>
<servlet-name>testConnectionPooler</servlet-name>
<servlet-class>com.test.web.TestServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
启动Tomcat
出现信息如下
2004-3-20 21:28:05 org.apache.commons.modeler.Registry getRegistry
信息: Creating new Registry instance
2004-3-20 21:28:06 org.apache.commons.modeler.Registry getServer
信息: Creating MBeanServer
2004-3-20 21:28:07 org.apache.coyote.http11.Http11Protocol init
信息: Initializing Coyote HTTP/1.1 on port 80
Starting service Tomcat-Standalone
Apache Tomcat/4.1.27-LE-jdk14
2004-03-20 21:28:11,843 INFO [main] web.TestServlet (TestServlet.java:43) - 连接池OK
2004-3-20 21:28:13 org.apache.struts.util.PropertyMessageResources <init>
信息: Initializing, config='org.apache.struts.util.LocalStrings', returnNull=true
2004-3-20 21:28:13 org.apache.struts.util.PropertyMessageResources <init>
现在我们关闭MySQL数据库服务,再重新启动Tomcat
出现信息如下
2004-3-20 21:26:48 org.apache.commons.modeler.Registry getRegistry
信息: Creating new Registry instance
2004-3-20 21:26:49 org.apache.commons.modeler.Registry getServer
信息: Creating MBeanServer
2004-3-20 21:26:50 org.apache.coyote.http11.Http11Protocol init
信息: Initializing Coyote HTTP/1.1 on port 80
Starting service Tomcat-Standalone
Apache Tomcat/4.1.27-LE-jdk14
2004-03-20 21:26:55,421 ERROR [main] web.TestServlet (TestServlet.java:48) - 出现错误Cannot create PoolableConnectionFactory
2004-3-20 21:26:56 org.apache.struts.util.PropertyMessageResources <init>
信息: Initializing, config='org.apache.struts.util.LocalStrings', returnNull=true
2004-3-20 21:26:56 org.apache.struts.util.PropertyMessageResources <init>

好了数据库连接已经成功,接下来我们重新配置Hibernate,使其支持连接池
我们修改配置文件Hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">java:comp/env/jdbc/mysql</property>
<property name="show_sql">false</property>
<property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
<mapping resource="com/yjsoft/hbm/UserInfo.hbm.xml"/>
</session-factory>

</hibernate-configuration>
修改web.xml添加
<servlet>
<servlet-name>testConnectionPooler</servlet-name>
<servlet-class>com.test.web.TestHBMServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
测试的Servlet如下
package com.test.web;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.MappingException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.cfg.Configuration;

import org.apache.log4j.Logger;

import com.yjsoft.hbm.UserInfo;
/**
* @author yanghx
*
* 更改所生成类型注释的模板为 窗口 > 首选项 > Java > 代码生成 > 代码和注释
*/
public class TestHBMServlet extends HttpServlet {
private static Logger log = Logger.getLogger(TestHBMServlet.class);
public void init() throws ServletException {
super.init();
Configuration cfg = null;
SessionFactory sf = null;
//SchemaExport pTemp = null;
Session s = null;
try {
//cfg = new Configuration();
cfg = new Configuration().configure("/hibernate.cfg.xml");
//cfg.addClass(UserInfo.class);
} catch (MappingException e1) {
e1.printStackTrace();
log.error("映射错误:" + e1);
return;
} catch (HibernateException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
log.error("映射错误:" + e);
return;
}
try {
//pTemp = new SchemaExport(cfg);
//pTemp.create(true, true);
sf = cfg.buildSessionFactory();
s = sf.openSession();
} catch (HibernateException e) {
e.printStackTrace();
log.error("Hibernate 错误" + e);
return;
}
try {
log.info("Open Session OK");

long start = System.currentTimeMillis();
for (int i = 0; i < 10; i++) {
UserInfo message = new UserInfo();
message.setId(String.valueOf(i));
message.setUserName(String.valueOf(i));
message.setPassword(String.valueOf(i));
try {
s.save(message);
s.flush();
//s.evict(message);
} catch (HibernateException e4) {
e4.printStackTrace();
log.error("Hibernate Insert 错误" + e4);
return;
}
}
long end = System.currentTimeMillis();
log.info(new Long(end - start));
}
catch(Exception e){
e.printStackTrace();
log.error("Hibernate Insert 错误" + e);
return;
}
finally {
try {
s.close();
} catch (HibernateException e4) {
e4.printStackTrace();
log.error("Hibernate Close 错误" + e4);
}
}
}
}
启动Tomcat,显示如下:
信息: Creating new Registry instance
2004-3-20 22:58:04 org.apache.commons.modeler.Registry getServer
信息: Creating MBeanServer
2004-3-20 22:58:05 org.apache.coyote.http11.Http11Protocol init
信息: Initializing Coyote HTTP/1.1 on port 80
Starting service Tomcat-Standalone
Apache Tomcat/4.1.27-LE-jdk14
2004-03-20 22:58:11,734 INFO [main] web.TestHBMServlet (TestHBMServlet.java:58) - Open Session OK
2004-03-20 22:58:11,890 INFO [main] web.TestHBMServlet (TestHBMServlet.java:77) - 140
2004-3-20 22:58:13 org.apache.struts.util.PropertyMessageResources <init>
信息: Initializing, config='org.apache.struts.util.LocalStrings', returnNull=true
2004-3-20 22:58:13 org.apache.struts.util.PropertyMessageResources <init>
这样 Hibernate配置利用Tomcat的连接池成功。

注意点:
l 不能利用cfg = new Configuration().configure("/hibernate.cfg.xml");创建Configure以后再利用cfg.addClass(…)这样配置以后只能利用配置文件中的<mapping resource=“”/>
l 因为已经利用了hibernate.properties所以在编写其他时候一定要用cfg = new Configuration().configure("/hibernate.cfg.xml")来配置Configure
l 删除文件hibernate.properties

现在我们开始编写实例Logon程序
利用Struts1.1
利用MyEclipse向导

第2步

创建Form,Action,以及相应的JSP文件

添加用户名属性

添加密码属性

下一步

下一步

分别添加Forward


最后

下面我们编写生成的文件

首先LogonForm.java文件
public ActionErrors validate(
ActionMapping mapping,
HttpServletRequest request) {
ActionErrors errors=super.validate(mapping,request);
if(errors==null){
errors=new ActionErrors();
}
if((password==null)||(password.trim().length()==0)){
errors.add("password",new ActionError("password"));
}
if((userName==null)||(userName.trim().length()==0)){
errors.add("userName",new ActionError("userName"));
}
return errors;
}
修改Action类
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
LogonForm logonForm = (LogonForm) form;
Session s = null;
try {
s = YJBaseHBM.currentSession();
} catch (HibernateException e) {
e.printStackTrace();
ActionErrors errors = new ActionErrors();
errors.add("hbm.session.error",
new ActionError("hbm.session.error"));
saveErrors(request, errors);
return mapping.findForward("failure");
}
try {
Query q=s.createQuery("from UserInfo ui where ui.userName=:user and password=:password");
q.setString("user", logonForm.getUserName());
q.setString("password", logonForm.getPassword());
System.out.println(q.toString());
Iterator it = q.iterate();
if(it.hasNext()==false){
ActionErrors errors = new ActionErrors();
errors.add("no.user",
new ActionError("no.user"));
saveErrors(request, errors);
return mapping.findForward("failure");
}
YJBaseHBM.closeSession();
} catch (HibernateException e) {
e.printStackTrace();
ActionErrors errors = new ActionErrors();
errors.add("hbm.session.query",
new ActionError("hbm.session.query"));
saveErrors(request, errors);
return mapping.findForward("failure");
} catch (Exception e1){
e1.printStackTrace();
ActionErrors errors = new ActionErrors();
errors.add("hbm.session.query",
new ActionError("hbm.session.query"));
saveErrors(request, errors);
return mapping.findForward("failure");
}

return mapping.findForward("success");
}
logon.jsp与struts-config.xml配置修改见下载文件
测试:

用户名为空:

数据库中没有帐号

今天任务完成。下次讲Struts1.1中与JSP页中错误处理。

对时间总结:
l 在调试Hibernate利用Tomcat中连接池的时候一直没有删除hibernate.properties,导致错误原因没有办法查找
l 在调试Demo时,没有将测试的Servlet在Web.xml中删除,出现插入时主键重复
l Eclipse3这个版本在右键XML文件时,老是导致我CPU100%

下载文件:http://www.wds.gov.cn/UpImage/2004321510.rar
从这一期开始进入正题,以一个留言版讲解Struts与Hibernate的开发。
关于留言版的页面Layout设计请参见附件的Excel文档。

首先我们按照惯例,写好计划表


首先我们准备好制作UTF-8工具
Native2Ascii 这个文件在JDK得bin目录下,利用方法如下
Native2ascii –ecoding GBK C:/GBKSource.txt C:/UTF8Source.txt

利用Struts资源文件达到国际化。
修改上次得Logon.jsp文件
<%@ page language="java"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>
<html>
<head>
<title><bean:message key="Logon"/></title>
</head>
<body>
<html:errors property="hbm.session.error"/>
<html:errors property="no.user"/>
<html:errors property="hbm.session.query"/>
<html:form action="/jsp/logon.do" focus="userName">
<bean:message key="Logon.UserName"/> : <html:text property="userName"/><html:errors property="userName"/></br>
<bean:message key="Logon.Password"/> : <html:text property="password"/><html:errors property="password"/></br>
<html:submit/>
</html:form>
<body>
</html>
我们编写资源文件
password=<font color=red>密码格式错误</font>
userName=<font color=red>帐号格式错误</font>
hbm.session.error=建立Hibernate Session 错误。
no.user=找不到这样得用户。
hbm.session.query=Hibernate HQL 查询错误。
errors.header=</font color=red><ul>
errors.footer=</ul></font>
Logon=登陆
Logon.UserName=帐号
Logon.Password=密码
保存到C:/1.txt
然后运行
native2ascii -encoding GBK C:/1.txt C:/ApplicationResources_zh_CN.properties
将生成得C:/ApplicationResources_zh_CN.properties拷贝到src目录下,我们重新运行此登陆程序。
出现乱码,我们忘了将JSP页面编码设成UTF-8了,添加
contentType="text/html;charset=UTF-8",再次刷新

OK成功
当你在帐号框里面输入中文,但是没有通过,就会出现下图现象。

又出现乱码,这样的情况解决办法有3个:
1. 在每一个Action里面设置Response得编码,这种方法比较繁琐,每一个Action必须设置一次。
2. 利用Servlet2.3里面得过滤器,统一设置编码
3. 重载ActionServlet里面的Process函数。

第1种方法很难通过XML配置来获得编码方式。
2,3可以通过Web.xml里面配置参数来解决
本文讲述时利用方式2,过滤器Filter
在Tomcat里面的samples里面的Filter文件夹下有现成的编码过滤器。
拷贝来,在Eclipse利用重构,解决package不匹配问题。
下面为这个过滤器配置web.xml
<!--
Filter
-->
<filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>com.yjsoft.filter.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
end
-->
再次启动Tomcat测试,OK。
下面开始处理JSP页面出错情况
添加错误页面,内容如下:
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page isErrorPage="true" %>
……其他省略,请看源文件
当要在其他页面处理Exception时,只要在头部添加
<%@ page errorPage="error.jsp" %>
测试如下:
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib uri="/tags/struts-bean" prefix="bean"%>
<%@ taglib uri="/tags/struts-html" prefix="html"%>
<%@ page errorPage="error.jsp" %>
<%
int n=0;
int n1=10/n;
%>
请求时转向出错页面:

下面测试Action中的Exception。
现在我们开始为Action中的异常定义处理。
先配置全局Exception
<global-exceptions>
<exception key="errors.message" path="actionerror.jsp" scope=”request” type="java.lang.Exception" />
</global-exceptions>
修改我们的LogonAction,使其抛出一个异常。这样全局配置文件就可以进行处理了

上面的验证是通过Server端来的,我们继承了ActionForm,其实我们有一种更简单的方式,那就是利用Validator组件。
使用validator组件,既可以支持客户端的验证,同时Server端也进行同样验证。同时验证方式可以重用。
我们来认识一下Struts1.1的Validator。
1.Validators
一个Validator就是,执行一个验证规则时Validator框架调用的一个Java类。框架根据配置文件中定义的方法签名来调用这个Validaotor类。一般情况下,每个Validator类提供一个单独的验证规则,然后这些规则可以组合成更复杂的规则集。Validator框架提供了Web应用程序需要的大多数的验证规则。你可以使用这些现有的验证规则来创建自己验证配置文件。我们也可以根据需要随意的增加更多的Validator。

2.配置文件
Struts1.1的Validator框架,用到这样两个配置文件,一个叫validator-rules.xml,另一个叫validation.xml;其实你也可以随意的给他们命名,甚至可以把它们合并成一个XML文件。但是,你还是最好把它们分开,因为它们各有各的用途。
Validator-rules.xml文件
validator-rules.xml文件定义应用程序可以使用的Validator。Validator-rules.xml充当模板的作用,定义所有应用程序可能要用到的Validator。

下面我们重新设计我们的LogonForm
改为
public class LogonForm extends ValidatorForm/*ActionForm*/
我们注释掉ActionForm的Validate()函数。
我们配置Struts-config.xml文件,在文件最后增加
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" />
</plug-in>

下面我们修改validation.xml文件
增加
<form name="logonForm">
<field
property="userName"
depends="required">
<arg0 key="userName" resource="false"/>
</field>
<field
property="password"
depends="required">
<arg0 key="password" resource="false"/>

</field>
</form>
同时在资源文件中增加
errors.required={0} is required.

重新启动程序,那么登陆程序服务器端验证就起作用了。
下面我们来添加Client端的Javascript验证。

修改Logon.jsp
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib uri="/tags/struts-bean" prefix="bean"%>
<%@ taglib uri="/tags/struts-html" prefix="html"%>
<%@ page errorPage="error.jsp" %>

<html>
<head>
<title><bean:message key="Logon"/></title>
</head>
<body>
<html:errors property="hbm.session.error"/>
<html:errors property="no.user"/>
<html:errors property="hbm.session.query"/>
<html:form action="/jsp/logon.do" focus="userName"
onsubmit="return validateLogonForm(this)">
<bean:message key="Logon.UserName"/> : <html:text property="userName"/><html:errors property="userName"/></br>
<bean:message key="Logon.Password"/> : <html:text property="password"/><html:errors property="password"/></br>
<html:submit>
<bean:message key="Logon.Submit"/>
</html:submit>
</html:form>
<html:javascript dynamicJavascript="true" staticJavascript="true" formName=”logonForm”/>

<body>
</html>


OK
最后陪伴我的只是那半支烟...[size=5]文字

体会真正的Struts开发, 比较详细

开发的东西传一个来看看

体会真正的Struts开发, 比较详细

好的,不过我现在在长沙,没回学校。呵呵
最后陪伴我的只是那半支烟...[size=5]文字

体会真正的Struts开发, 比较详细

***** 版主模式 *****
这篇帖子没有包含原创内容,先放到计算机技巧里面
该帖子是管理员从<a href=forums.cgi?forum=4>☆程序人生☆</a>转移过来的!

                     我是一个呼吸着现在的空气而生活在过去的人
               这样的注定孤独,孤独的身处闹市却犹如置身于荒漠
                                     我已习惯了孤独,爱上孤独
                                 他让我看清了自我,还原了自我
                             让我再静静的沉思中得到快乐和满足
                                   再孤独的世界里我一遍又一遍
                                   不厌其烦的改写着自己的过去
                                             延伸到现在与未来
                                       然而那只是泡沫般的美梦
                                 产生的时刻又伴随着破灭的到来
                         在灰飞烟灭的瞬间我看到的是过程的美丽
                                      而不是结果的悲哀。。。
返回列表