Struts程序开发全攻略

uniapp使用webview嵌入vue页面及通信 最终方案就是在uniapp中获取那一大串儿json,然后传递到webview页面进行渲染,然后提交表单的时候再通知webview页面(Vue页面)将表单json再传递给uniapp进行提交。所以就涉及到了uniapp与webview之间的通信问题,接下来介绍: 阅读详情

Struts程序开发全攻略

 

1.概述

这篇文章主要通过一步一步的操作来讲述在Windows系统中开发Struts程序的过程。本篇文章注重实践,相关概念不会详细讲述。本文并没有提到有关CVS的安装和配置,如果感兴趣,可以参考另外一篇文档:CVS的配置和使用

2.相关工具

在开发过程中我们主要使用以下工具:

l         Apache 2.0.46                 主页:http://httpd.apache.org/

l         JDK 1.4.2                       主页:http://java.sun.com/j2se/index.jsp

l         Tomcat 5.0.12                主页:http://jakarta.apache.org/tomcat/index.html

l         Struts1.1                      主页:http://struts.apache.org/

l         Ant 1.5.2                        主页:http://ant.apache.org/

l         Log4j 1.2.8                     主页:http://logging.apache.org/log4j/docs/index.html、

l         Eclipse3.0                     主页:http://www.eclipse.org/

l         Lomboz3.01                 主页:http://www.objectlearn.com/index.jsp

l         MySQL Standard 4.0.20 主页:http://www.mysql.com

 

以上工具都是开源的,可以从相应的主页上免费下载。其中Ant在Eclipse3.0(一个十分出色的JAVA IDE)中已经集成,可以不用下载。如果想了解更多的信息,可以到主页上查看相关的文档。

3.环境搭建

3.1 安装JDK

安装JDK可以按着提示进行安装,没有什么特别需要注意的,安装的时候我个人喜欢安装JDK的源码,这样查东西的时候方便一些。从sun的网站上也可以下载J2SDK的API文档,把文档解压到JDK的安装目录中,这些文档在以后的开发过程中十分重要,我们会经常查阅。安装之后,需要一些配置工作。下面主要讨论一下如何配置。

增加环境变量:右键点击我的电脑->属性->高级->环境变量

增加JAVA_HOME系统变量,内容为jdk的安装路径,如下图所示:

图 1

增加了JAVA_HOME环境变量之后,就可以利用JAVA_HOME增加其他的环境变量了,这样如果JDK重新安装到其他的目录(比如更换版本),就不用修改所有的环境变量了,只修改一个JAVA_HOME就可以了。

增加CLASSPATH环境变量。内容为

.;%JAVA_HOME%/lib/dt.jar;%JAVA_HOME%/lib/tools.jar

CLASSPATH环境变量表示在java程序运行的时候需要调用的包,如果加入到环境变量中就不用在每次执行的时候都用命令行参数指出(-classpath)。最开始的英文句号代表当前目录,表示如果运行java程序的时候要在当前目录中寻找相应的类或者包。有些人在命令行下调试java程序的时候经常出现java.lang.NoClassDefFoundError错误,就很有可能是CLASSPATH环境变量设置出错。

增加环境变量PATH。环境变量PATH是表示在命令行下运行的命令的寻找路径。设置好PATH之后,就可以在任何目录下运行java和javac等命令了。如果不闲麻烦,也可以每次运行的时候都%JAVA_HOME%/bin/java。PATH是系统自带的环境变量,只要在已有的PATH中增加%JAVA_HOME%/bin就可以了,注意用分号与其他的路径分开。

现在JDK的安装基本上就完成了。

3.2 安装Apache2

安装Apache2的过程中,需要填写一些信息,比如域名之类的,随便填写一下就可以了,servername填写本机的机器名就可以了,如图2 所示。

图 2

下一步安装的时候选择自定义安装,这样可以修改Apache2的安装路径。选择D:/根目录,这样安装之后是的目录是D:/Apache2。安装之后在系统托盘中会出现Aapche Monitor的图标,可以通过这个图标重启Apache的服务。

为了避免和IIS冲突,我们把Apache的启动端口更改为8024,当然也可以关闭IIS的服务,或者更改IIS的启动端口。编辑Apache安装目录中的conf/httpd.conf文件,找到Listen 80,把80修改成8024,重新启动Apache服务即可。访问http://localhost:8024,如果出现如图3所示页面,表示Apache安装成功。

 

图3

3.3 安装Tomcat

安装Tomcat之前,必须正确安装了JDK。

安装的时候选择安装成服务,如图4所示:

图4

选择完安装目录之后,会有一个配置界面,如图5所示,选择安装服务的端口后,以及管理员的用户名和密码。默认的端口号是8080,我们保持默认值。记住填写的用户名和密码,在以后的管理工作中需要用到。如果忘记的话,可以在tomcat的安装路径中的conf/tomcat-users.xml文件中找到。

图5

下一个界面是JAVA虚拟机(JVM)的路径,默认的情况下,应该是JDK的安装路径,如果没有默认值,通过浏览也可以选择。

安装完毕之后,在系统托盘中会出现Apache Tomcat的图标,可以利用这个图标启动和关闭服务。

启动tomcat服务,访问http://localhost:8080,如果出现如图6所示的页面,表示安装成功。

图 6

 

3.4 安装Eclipse3.0

Eclipse是由IBM等多家公司资助的开源项目,包括一个核心的平台,其他的功能都是一些plugins,系统很容易扩展,并且支持本身插件的开发。Eclipse有支持java开发JDT的开发,同时也有支持C++开发的CDT。Eclipse最新的稳定版本是3.0。

Eclipse安装十分简单,只要正确安装了JDK,把下载的Eclipse压缩包解压到一个目录中,执行目录中的eclipse.exe文件即可。第一次执行,Eclipse会做一些初始化的工作。要设定系统得工作目录,就是工程的存放目录。默认的是Eclipse目录中的workspace目录,我们采用默认值。

进入之后,是一个Welcome界面,里面有一些功能介绍等。关掉之后可以看到以下界面,如图7所示

图 7

第一步工作就是设置JDK。打开菜单Window->Preferences,打开节点Java->Installed JREs,如图8所示。

图 8

默认的情况下应该已经有了系统安装的默认的JDK列表。选择之后,点击Edit…,弹出Edit JRE对话框,如图9所示。

图 9

大部分信息不用修改,我们只修改Javadoc URL的内容。Eclipse默认的情况下指向java.sun.com网站。点击Browse…弹出对话框,选择我们刚才解压的javadoc的目录。注意一定要指到api的那一层,否则Eclipse不能找到相应的API文档,如图10所示。

图 10

在Eclipse中有一个名词叫作Perspective,我个人觉得就是不同的界面表现形式。Eclipse默认的采用Resource Perspective,如果开发JAVA程序,还是采用Java Perspective比较好用。想切换Perspective,可以点击右上角的图标,如图11所示。

图 11

 

3.5 安装Lomboz

Eclipse开发JAVA的程序比较得心应手,但是开发Web程序就显得力不从心了。我们需要Lomboz插件的帮忙。Lomboz支持jsp语法的高亮和提示,并且支持自定义的taglib。同时利用Lomboz开发EJB也是不错的选择。Lomboz安装之前需要EMF插件。所以要想Lomboz可用,必须也要安装EMF。安装方法也很简单,把下载的ZIP包解压到Eclipse目录下,覆盖plugins和features目录就可以了。然后重新启动Eclipse。Lomboz要想正常使用还需要做一些配置。配置方法如下:

选择Window->Preferences,选择Lomboz节点,修改JDK Tools.jar的内容,指向$JAVA_HOME$/lib/tools.jar,如图12所示。

图 12

 

我们这里主要用Lomboz编辑JSP文件的功能,如果想开发J2EE的程序,Lomboz还需要一些其他的设置,由于篇幅的原因,我就在这里不再详细讲述,如果感兴趣,可以参考Lomboz Tutorials(http://www.objectlearn.com/support/docs/index.jsp),这里有比较详细的配置和开发方法。

3.6 安装MySQL

安装MySQL按着向导安装即可,安装之后运行MySQL安装目录中的/bin/winmysqladmin.exe文件,第一次运行的时候会显示如图13所示的对话框,填写用户名密码,这个用户名密码不知道有什么用,MySQL默认的用户是root,密码为空。在实际的部署过程中,要注意修改默认密码。

图 13

如果在系统托盘中的红绿灯图标中显示绿灯,那么表示MySQL正常启动。为了方便以后使用,建议把MySQL/bin目录添加到PATH环境变量中,参看3.1。

至此,开发工具已经全部安装完毕,Struts、MySQL JDBC Driver和log4j我们只是需要相应得jar文件,我们在开发struts应用的时候放到相应的目录中即可。

4.程序开发

前面说了一大堆废话,下面我们就进入实质性的工作,开发程序。我们的应用十分简单,就是一个用户注册和用户登录的功能。应用的名字为mystruts。

4.1 配置tomcat连接池

首先我们在tomcat的目录中安装MySQL JDBC Driver。解开从MySQL网站下载的最新的JDBC Driver 安装包:mysql-connector-java- 3.0.14 -production.zip,找到文件mysql-connector-java-3.0.14-production-bin.jar,这个就是我们需要的JDBC Driver,把这个文件拷贝到tomcat/common/lib目录中即可。

接下来要配置JDBC的连接池。修改tomcat/conf/server.xml文件。

在文件的最后面</Host>之前增加以下的内容:

<Context path="/mystruts" docBase="mystruts" debug="0" reloadable="true"

crossContext="true">

    <Resource name="jdbc/mystruts" auth="Container"

                    type="javax.sql.DataSource"/>

     <ResourceParams name="jdbc/mystruts">

            <parameter><name>username</name><value>mystruts</value></parameter>

            <parameter><name>password</name><value>mystruts</value></parameter>

 <parameter><name>driverClassName</name><value>com.mysql.jdbc.Driver</value></parameter>

            <parameter><name>url</name><value>jdbc:mysql://localhost/mystruts?useUnicode=true&amp;characterEncoding=iso-8859-1</value></parameter>

     </ResourceParams>

     </Context>

这里面存储的访问数据库的用户名密码和MySQL所在的机器地址等信息。做完以上工作,需要重新启动tomcat才会生效。

4.2 增加MySQL的访问用户

上面的连接池中配置了访问MySQL的用户名密码,要想正确的访问,那么就需要在MySQL中增加相应的用户。

在命令行中执行mysql命令,进入mysql。首先我们先创建mystruts数据库,命令如下:

mysql> create database mystruts;

系统会提示:Query OK, 1 row affected (0.06 sec),表示创建成功。然后我们为这个数据库添加访问用户。命令如下:

mysql> grant all on mystruts.* to mystruts@localhost identified by 'mystruts';

grant all是表示把所有的权限(增加、删除、修改表和用户授权的操作)付给制定的用户,on mystruts.*表示mystruts库中的所有的表,to mystruts@localhost表示权限是付给本机的mystruts用户,也就是说mystruts只能在本机访问数据库,从其他的机器上访问,即便用户名密码正确也是没有权限的。identified by ‘mysturts’表示用户的密码是mystruts。通过以上的操作,就建立了一个只能在localhost上对mystruts数据库进行完全操作的mystruts用户。为了验证建立用户是否正确,我们可以退出mysql,在命令行下运行如下命令:

C:/>mysql mystruts -umystruts -pmystruts

如果提示成功,那么表示建立的用户是正确的。

创建user表,我们将在mystruts web程序中使用这个表。创建语句如下:

mysql> create table user (id int(11) auto_increment not null default 0 primary key ,

    -> name varchar(20) not null default '',

    -> passwd varchar(20) not null default '',

    -> email varchar(30) not null default '');

4.3 在Eclipse中建立工程

现在我们打开Eclipse,File->new->Project,显示新建工程对话框,我们选择Java Project工程。单击Next。下一个对话框需要填写工程名称,我们定义为mystruts,其他的选项保持默认值。单击Next。我们在这个对话框中选择Source,然后单击Add Folder按钮,增加src目录作为源代码目录。同时修改下面的Default Output Folder改成mystruts/classes目录,然后点击Finish,工程建立完成。

在工程中,我们应该有以下几个目录:

src目录:存放JAVA源代码和一些必要的配置文件

jsp目录:存放jsp文件

html目录:存放静态的html文件和图片文件,这个目录的东西在部署的时候需要进行拷贝到Apache目录中。

WEB-INF目录:存放配置文件。

WEB-INF/lib目录:存放我们需要引用的第三方类库jar文件,struts和log4j中解压出来的文件也放到这个目录中,文件分别是struts.jar、struts-legacy.jar、log4j- 1.2.8 .jar。

WEB-INF/classes目录:存放我们写的程序的编译出来的class文件,第三方的没有大包成jar文件的包也放到这个目录。

WEB-INF/tld目录:存放struts需要用到的标签库。

工程根目录中还有两个文件:build.xml和build.properties文件,这两个文件是在ant编译部署的时候使用。

添加工程需要的类库。Project->Properties,选择Java Build Path->Libraries,然后单击Add JARs…按钮,将WEB-INF/lib目录下的所有jar文件添加到Libraries中。如图14所示。

图 14

确定之后,还要添加一个外部jar(不在工程目录中的),单击Add External JARs,把tomcat/common/lib/servlet-api.jar文件添加进来。

编辑WEB-INF目录中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-beans>

 

    <global-forwards>

    </global-forwards>

 

    <action-mappings>

    </action-mappings>

    <message-resources parameter="mystruts"/>

</struts-config>

主要分为四个部分:form-beans,global-forwords,action-mapping,message-resource。其中message-resource是用来指定struts指定的资源文件的名字。如上所示,mystruts表示资源文件是在WEB-INF/classes/mystruts.properties,同理,如果写成com.testing.hao2k.mystruts,那么资源文件就应该是WEB-INF/classes/com/testing/hao2k/mystruts.properties。利用这种方式可以很容易的实现国际化,让中文用户访问的时候看到中文界面,英文用户访问同一个网站的时候显示英文界面,具体方法我们在以后再介绍。

4.4 编写代码

在src目录中建立三个package:com.testing.hao2k,com.testing.hao2k.forms,com.testing.hao2k.actions,分别存放数据库操作类、struts中的ActionForm类、struts中的Action类。

我们先完成用户注册的模块。

用户注册需要以下信息:用户名、密码、电子邮件等信息。

进入系统之后首先是欢迎的页面,文件名是index.jsp,我们把这个文件放到jsp目录中,文件的代码如下:

 

<%response.setContentType("text/html");%>

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

<html>

<head>

<title><bean:message key="jsp.index.title"/></title>

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

</head>

 

<body leftmargin="0" topmargin="0" align="center">

<p>

    <bean:message key="jsp.index.welcome"/>

</p>

<p>

    <a href="login.jsp"><bean:message key="jsp.index.login"/></a>

</p>

<p>

<a href="register.jsp"><bean:message key="jsp.index.register"/></a>

</p>

</body>

</html>

 

第一句是设置这个页面的contentType,语言环境主要没有设置,默认的是ISO-8859-1,我们采用默认值,经验证明,这样做可以解决大部分的JAVA Encoding问题。第二句是声名使用到的struts标签。bean:message是用来从配置文件中读取内容,然后把内容显示到页面上。只要我们修改相应的配置文件,界面上的文字就会改变,我们并不需要修改源代码。

下面是register.jsp页面的内容:

 

<%response.setContentType("text/html");%>

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

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

<html>

<head>

<title><bean:message key="jsp.register.title"/></title>

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

</head>

 

<body leftmargin="0" topmargin="0" align="center">

<p align="center">

    <bean:message key="jsp.register.welcome"/>

</p>

<p align="center">

    <font color=red align="center"><html:errors /></font>

</p>

<html:form action="regAction" method="post">

<table align="center">

    <tr>

       <td><bean:message key="jsp.register.username"/></td>

       <td><html:text property="username"></html:text></td>

    </tr>

    <tr>

       <td><bean:message key="jsp.register.passwd"/></td>

       <td><html:password property="passwd" ></html:password></td>

    </tr>

    <tr>

       <td><bean:message key="jsp.register.repasswd"/></td>

       <td><html:password property="repasswd" ></html:password></td>

    </tr>

    <tr>

       <td><bean:message key="jsp.register.email"/></td>

       <td><html:text property="email" ></html:text></td>

    </tr>

    <tr>

       <td>

<html:submit>

<bean:message key="jsp.register.save"/>

</html:submit>

</td>

       <td>

<html:reset>

<bean:message key="jsp.register.reset"/>

</html:reset>

</td>

    </tr>

</table>

</html:form>

</body>

</html>

 

在这个jsp文件中,我们需要几个地方需要注意。代码中的<html:errors/>是根据FormAction中的validate方法中是否有错误添加,如果有,那么会在这个地方显示,具体的实现我们会在介绍FormAction的时候讨论。

另外一个地方就是<html:form action="regAction" method="post">。这个是Struts中的一个标签,经过转化之后相当于html中的<form>语句。这里面的action中的值是与struts-config.xml配置文件相对应的。代码如下所示:

<action-mappings>

<action path="/regAction" type="com.testing.hao2k.actions.RegisterAction"            name="RegisterForm" input="/jsp/register.jsp" scope="request">

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

                 </forward>

        </action>

    </action-mappings>

 

找到path为resAction的action节点,这里面有关于这个action的一些信息。Type为这个action对应的类的完全路径,input对应是从哪个页面访问这个action的,如果在ActionForm中出现数据验证错误,会自动返回到这个页面,并且把用户输入的信息保留下来,填写到适当的地方。以前我们为了实现这个功能,都是要在servlet中设置相应得属性,然后再jsp页面中再读取,现在Struts帮助我们作了这部分的工作。Forword标签是根据操作的状态,在action操作之后返回到相应得页面。name中对应的属性是指这个action对应的ActionForm类。这个值与struts-config.xml文件中的formbean定义相关联。如下所示:

    <form-beans>

<form-bean name="RegisterForm" type="com.testing.hao2k.forms.RegisterForm">

        </form-bean>

    </form-beans>

 

其中的type对应实际的ActionForm类。RegisterForm.java文件的内容如下所示:

/*

 * Created on 2004-9-3

 */

package com.testing.hao2k.forms;

 

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;

 

public class RegisterForm extends ActionForm {

    private String username;

 

    private String passwd;

 

    private String repasswd;

 

    private String email;

 

    /**

     * @return Returns the email.

     */

    public String getEmail() {

        return email;

    }

 

    /**

     * @param email

     *            The email to set.

     */

    public void setEmail(String email) {

        this.email = email;

    }

 

    /**

     * @return Returns the name.

     */

    public String getUsername() {

        return username;

    }

 

    /**

     * @param name

     *            The name to set.

     */

    public void setUsername(String name) {

        this.username = name;

    }

 

    /**

     * @return Returns the passwd.

     */

    public String getPasswd() {

        return passwd;

    }

 

    /**

     * @param passwd

     *            The passwd to set.

     */

    public void setPasswd(String passwd) {

        this.passwd = passwd;

    }

 

    /**

     * @return Returns the repasswd.

     */

    public String getRepasswd() {

        return repasswd;

    }

 

    /**

     * @param repasswd

     *            The repasswd to set.

     */

    public void setRepasswd(String repasswd) {

        this.repasswd = repasswd;

    }

 

    public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {

        ActionErrors errors = new ActionErrors();

        if (username == null || username.length() < 1) {

            errors.add("username", new ActionError("error.username.input"));

        }

        if (passwd == null || passwd.length() < 1) {

            errors.add("passwd", new ActionError("error.passwd.input"));

        }

        if (passwd != null && !passwd.equals(repasswd)) {

            errors.add("repasswd", new ActionError("error.password.match"));

        }

        if (email == null || email.length() < 1 || email.indexOf("@") < 1) {

            errors.add("email", new ActionError("error.email.input"));

        }

        return errors;

    }

}

这个类主要分为两个部分,前面是所有属性的getter和setter函数。这些函数的命名需要与jsp文件的form中的变量相对应。例如form中有username变量,那么在ActionForm就要有对应于username的getter和setter函数。分别命名为getUsername()和setUsername()。规则是变量名的第一个字母大写,其他的不变,然后在前面加上get和set。ActionForm之所以可以自动读取jsp页面中的变量,就是利用这种对应关系实现的。这种对应关系在ActionForm中是十分重要的,如果对应不正确,那么就不能正常工作。

第二部分主要是validate函数,这个函数会在用户提交之后自动调用,主要的功能是来验证用户输入的数据是否正确,如果出现非法的数据,那么会把相应的错误加入到ActionErrors对象中,也就是这个函数的返回值。如果有错误,那么就会返回到input页面中,通过<html:errors/>来显示错误信息。在这一层直接返回,就不需要进入到action类中,减少系统负载。理论上说,如果在这里加入了足够的条件判断,那么在以后的数据处理当中就可以把数据当成是完全合法的,不用再做任何合法性的判断。如果在这个函数种没有任何的数据错误,那么ActionErrors对象中就为空,这样Sturts会自动判断,直接进入Action类中。

接下来,我们在com.testing.hao2k.entity包中创建User类。这个类是与数据库中的user表相对应,是数据持久层,类似于EJB中的实体bean。代码如下所示:

 

/*

 * Created on 2004-9-5

 */

package com.testing.hao2k.entity;

 

/**

 * @author Administrator

 */

public class User {

    private String username;

 

    private String passwd;

 

    private String email;

 

    /**

     * @return Returns the email.

     */

    public String getEmail() {

        return email;

    }

 

    /**

     * @param email

     *            The email to set.

     */

    public void setEmail(String email) {

        this.email = email;

    }

 

    /**

     * @return Returns the passwd.

     */

    public String getPasswd() {

        return passwd;

    }

 

    /**

     * @param passwd

     *            The passwd to set.

     */

    public void setPasswd(String passwd) {

        this.passwd = passwd;

    }

 

    /**

     * @return Returns the username.

     */

    public String getUsername() {

        return username;

    }

 

    /**

     * @param username

     *            The username to set.

     */

    public void setUsername(String username) {

        this.username = username;

    }

}

 

这个类的主要组成部分也是setter和getter函数。可能大家认为这个类和前面的RegisterForm类很象,为什么不共用这个类?表面上看,这两个类还是很象的,但是有着本质上的差别。RegisterForm是与表现层相关联的,是用户输入数据的抽象数据,用户输入的数据并不一定要加入到数据库中,比如验证密码。而User则是和数据库相对应的,每一个属性都对应于数据库中一个字段,它是数据持久层的类。

RegisterAction是Struts中的Action类,主要负责流程的控制。代码如下所示:

/*

 * Created on 2004-9-3

 *

 */

package com.testing.hao2k.actions;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.apache.struts.action.Action;

import org.apache.struts.action.ActionError;

import org.apache.struts.action.ActionErrors;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

 

import com.testing.hao2k.UserOP;

import com.testing.hao2k.forms.RegisterForm;

 

/**

 * @author Administrator

 * 

 */

public class RegisterAction extends Action {

    public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,

            HttpServletResponse response) throws Exception {

        ActionErrors errors = new ActionErrors();

        UserOP userOP = new UserOP();

        try {

            int result = userOP.add((RegisterForm) form);

            if (result == 1) {

                      errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionError("error.name.repeat"));

                saveErrors(request, errors);

                return mapping .findForward("failed");

            } else {

                errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionError("success.register.info"));

                saveErrors(request, errors);

                return mapping.findForward("success");

            }

        } catch (Exception e) {

            errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionError("error.register.dberror"));

            saveErrors(request, errors);

            return mapping.findForward("failed");

        }

    }

}

 

这个Action会调用相应得数据库操作类(我们会在下面介绍),根据操作的结果转向到不同的页面。同时在转向页面的过程中,还可以设定提示信息等。

下面我们构建一个类UserOP,专门用来对user表进行数据库操作的。在这个类中主要有四个方法:add,getUserByID,getAllUsers,validateUser。分别用于注册用户、根据用户ID得到用户、得到所有用户以及验证用户登录。代码如下所示:

/*

 * Created on 2004-9-6 11:11:52

 */

package com.testing.hao2k;

 

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.util.ArrayList;

 

import org.apache.log4j.Logger;

 

import com.testing.hao2k.entity.User;

import com.testing.hao2k.forms.LoginForm;

import com.testing.hao2k.forms.RegisterForm;

 

/**

 * @author Administrator

 */

public class UserOP {

    //实现日志操作的类

    private static Logger logger = Logger.getLogger(UserOP.class);

 

    /**

     * 实现注册用户的功能

     *

     * @param form

     *            保存着用户在HTML页面中填写的注册信息

     * @return 返回注册用户的状态值,成功返回0 如果数据库中已经有该用户,那么返回1

     * @throws Exception

     *             如果出现错误,那么抛出异常。

     */

    public int add(RegisterForm form) throws Exception {

        int result = 1;

        Connection conn = null;

        try {

            conn = DBConnection.getConnection();

            //查找是否在数据库中已经有重复的名字。

            String query = "select count(id) from user where name=?";

            PreparedStatement ps = conn.prepareStatement(query);

            ps.setString(1, form.getUsername());

            ResultSet rs = ps.executeQuery();

            if (rs.next()) {

                if (rs.getInt(1) > 0) {

                    //如果数据库中已经有该用户,那么返回1

                    result = 1;

                } else {

                    //                  添加新的用户

                    query = "insert into user (name,passwd,email) values (?,?,?)";

                    ps = conn.prepareStatement(query);

                    ps.setString(1, form.getUsername());

                    ps.setString(2, form.getPasswd());

                    ps.setString(3, form.getEmail());

                    ps.executeUpdate();

                    result = 0;

                }

            }

            rs.close();

            ps.close();

        } catch (Exception e) {

            logger.error(e);

            throw e;

        } finally {

            if (conn != null) {

                conn.close();

            }

        }

        return result;

    }

 

    /**

     * 根据用户的id返回用户对象

     *

     * @param id

     *            用户的id

     * @return 符合条件的用户对象,如果没有符合条件的用户返回null

     * @throws Exception

     *             如果出现异常,那么抛出

     */

    public User getUserByID(int id) throws Exception {

        User user = null;

        Connection conn = null;

        try {

            conn = DBConnection.getConnection();

            String query = "select * from user where id=?";

            PreparedStatement ps = conn.prepareStatement(query);

            ps.setInt(1, id);

            ResultSet rs = ps.executeQuery();

            if (rs.next()) {

                user = new User();

                user.setId(rs.getInt("id"));

                user.setUsername(rs.getString("name"));

                user.setPasswd(rs.getString("passwd"));

                user.setEmail(rs.getString("email"));

            }

            rs.close();

            ps.close();

        } catch (Exception e) {

            logger.error(e);

            throw e;

        } finally {

            if (conn != null) {

                conn.close();

            }

        }

        return user;

    }

 

    /**

     * 返回所有的用户,这是一个简单的例子,在实际应用中不建议返回所有的数据库记录 <br>

     * 这样会造成消耗大量的内存

     *

     * @return 返回ArrayList对象,里面存储着所有的用户。

     * @throws Exception 如果出现异常,那么抛出

     */

    public ArrayList getAllUsers() throws Exception {

        ArrayList allUsers = new ArrayList();

        Connection conn = null;

        try {

            conn = DBConnection.getConnection();

            String query = "select * from user";

            PreparedStatement ps = conn.prepareStatement(query);

            ResultSet rs = ps.executeQuery();

            while (rs.next()) {

                User user = new User();

                user.setId(rs.getInt("id"));

                user.setUsername(rs.getString("name"));

                user.setPasswd(rs.getString("passwd"));

                user.setEmail(rs.getString("email"));

                allUsers.add(user);

            }

            rs.close();

            ps.close();

        } catch (Exception e) {

            logger.error(e);

            throw e;

        } finally {

            if (conn != null) {

                conn.close();

            }

        }

        return allUsers;

    }

   

    /**

     * 验证登录用户是否合法

     *

     * @param name

     *            用户的用户名

     * @return 验证通过,返回0,否则返回1

     * @throws Exception

     *             如果出现异常,那么抛出

     */

    public int validateUser(LoginForm form) throws Exception {

        int result = 1;

        Connection conn = null;

        try {

            conn = DBConnection.getConnection();

            String query = "select * from user where name=? and passwd=?";

            PreparedStatement ps = conn.prepareStatement(query);

            ps.setString(1, form.getUsername());

            ps.setString(2,form.getPasswd());

            ResultSet rs = ps.executeQuery();

            if (rs.next()) {

                result = 0;

            }

            rs.close();

            ps.close();

        } catch (Exception e) {

            logger.error(e);

            throw e;

        } finally {

            if (conn != null) {

                conn.close();

            }

        }

        return result;

    }

}

这个类主要是通过action类调用的,不过也有同jsp调用的,比如getAllUsers方法。我们注意到在这个类中,数据库操作的时候都用到PreparedStatement类。这个类主要有两个好处,第一个是这个类会让数据库服务器事先编译sql语句,这在大用户量的情况下是十分有效的,其次通过setXXX方法,一些针对sql的特殊字符会进行转义,增强了系统的安全性。所以,我们建议,在数据库操作中尽量使用这个类去代替Statement类。

显示所有用户信息的jsp页面的代码如下:

<%response.setContentType("text/html");%>

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

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

<html>

<head>

<title><bean:message key="jsp.showallusers.title"/></title>

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

</head>

 

<body leftmargin="0" topmargin="0" align="center">

<p align="center">

    <bean:message key="jsp.showallusers.welcome"/>

</p>

<jsp:useBean id="allUserList" class="com.testing.hao2k.UserOP"/>

<table align="center" border=1>

    <tr>

       <td><bean:message key="jsp.register.username"/></td>

       <td><bean:message key="jsp.register.passwd"/></td>

       <td><bean:message key="jsp.register.email"/></td>

    </tr>

    <logic:iterate id="user" type="com.testing.hao2k.entity.User" name="allUserList" property="allUsers" >

    <tr>

       <td><bean:write name="user" property="username"/></td>

       <td><bean:write name="user" property="passwd"/></td>

       <td><bean:write name="user" property="email"/></td>

    </tr>

    </logic:iterate>

</table>

</body>

</html>

其中用到了logic:iterate标签。这是一个比较常用的标签,用来做循环的。循环是针对一个collection的,对collection中的内容作遍历,然后处理其中的内容。name属性用来标示一个已有的类,对这个类调用一个方法,返回collection,调用的方法在property属性中指定,对应类中的getAllusers()方法。type表示从collection中取得的元素要转换得类型。id表示collection中取得的元素转换之后生成的实例,在循环体内可以当作java变量使用。

bean:write标签表示要在页面上输出指定实例的属性。

登录的程序实现与注册的原理类似,大家可以参照源代码。

 

4.5 编译和部署程序

代码开发完毕,我们需要编译和部署程序,我们采用ant进行编译和部署。

Jakarta Project 将 Ant 工具说成“不带 make 缺点的 make”,(make是编译C语言的一个工具)。Ant 正在成为开放源代码世界中实际上的标准。原因很简单:Ant 是使用 Java 语言编写的,这种语言可以让构建过程在多种平台上使用。这种特性简化了在不同 OS 平台之间的程序员的合作,而合作是开放源代码社区的一种需要。您可以在自己选择的平台上进行开发和构建。Ant 的特性包括:

  • 类可扩展性:Java 类可用于扩展构建特性,而不必使用基于 shell 的命令。
  • 开放源代码:因为 Ant 是开放源代码,因此类扩展示例很充足。我发现通过示例来学习非常棒。
  • XML 可配置:Ant 不仅是基于 Java 的,它还使用 XML 文件配置构建过程。假设构建实际上是分层的,那么使用 XML 描述 make 过程就是其逻辑层。另外,如果您了解 XML,要学习如何配置构建就更简单一些。

 

图15简要介绍了一个配置文件,配置文件是标准的XML格式,由目标树构成。每个目标都包含了要执行的任务,其中任务就是可以执行的代码。在本例中,mkdir 是目标 compile 的任务。mkdir 是建立在 Ant 中的一个任务,用于创建目录。 Ant 带有一套健全的内置任务。您也可以通过扩展 Ant 任务类来添加自己的功能。

每个目标都有唯一的名称和可选的相关性。目标相关性需要在执行目标任务列表之前执行。如图15所示,在执行 compile 目标中的任务之前需要先运行 JUNIT 目标。这种类型的配置可以让您在一个配置中有多个树。

图 15

 

Eclipse对ant有着很好的支持,只要右键点击builid.xml,然后选择Ant Build,就可以执行默认的任务。

 

4.6 用struts轻松实现国际化

也许大家都看到过google的强大的国际化支持吧。有了struts我们就可以轻松的实现这种企业级网站的需求了。

前面大家已经看到,我们把所有页面中需要显示的信息都写到了一个叫做mystruts.properties的文件中,这就是为实现国际化做准备。如果要实现中文和英文用户访问看到不同界面语言的功能,我们就需要另外建立一个文件mystruts_zh.properties。从名字就可以看出,这个文件是用来存放中文信息的。我们把先前写到mystrut.properties文件中的内容复制到这个文件中,然后把mystruts.properties文件中的中文部分改成英文,然后部署到服务器上,重新启动tomcat就可以了。之所以重新启动tomcat,是因为这种机制是通过session实现的,session在用户第一次访问的时候记录的用户的语言信息。

现在让我们试一下,IE->工具->Internet选项->常规->语言->删除默认的中文,添加en_us,确定。然后再访问刚才的页面,就可以看到英文的页面了。在另外一台中文系统的机器上访问,看到的依然是中文界面。不过这种在配置文件中直接写中文的方法只适合与jsp页面中设置的语言是默认的iso-8859-1,如果设置成utf-8的,那么就需要对mystruts_zh.properties文件进行转换,否则页面显示将都是问号。利用native2ascii工具可以完成这个工作。

如果服务器端没有客户端IE使用的语言,那么struts会默认的找没有语言后缀的资源文件,比如如果有德语用户访问mystruts,那么就会显示mystruts.properties文件中的内容。

如果大家以后做的软件需要这种国际化的需求,那么用struts实现是再简单不过的了。

5.总结

上面我只是谈到了struts中的一部分功能,还有其他很实用的,包括template和生成JavaScript验证脚本的功能等,如果大家有兴趣可以参看struts中自带的例子。用struts开发,我个人认为最大的好处就是代码的模式化,每个人的代码都是十分相似的,即便是新加入到开发团队的人员,在其他团队成员的指导之下,也可以很快的掌握这一套开发流程。另外,struts具有很好的可扩展性,struts不仅可以和Hibernate联合使用,甚至也可以和EJB一起使用。

 

 

 

6、构建Web应用项目全攻略 本文详细介绍了使用NetBeans构建基于Struts框架的Web应用项目的全过程,涵盖添加Struts支持、创建表单和动作、配置struts-config.xml文件、构建与运行应用等内容。同时,还对比了多种Java应用服务器(如Tomcat、SJSAS、JBoss、WebLogic)的配置、控制及部署应用的方法,并提供了常见问题的解决策略和最佳实践建议,帮助开发者高效开发、测试和部署Web应用。 阅读详情

相关推荐

Struts2开发环境搭建全攻略

本文还有配套的精品资源,点击获取 简介:Struts2是一个功能强大的Java Web框架,它基于MVC架构,旨在提供灵活和可扩展的Web应用解决方案。本文将指导你如何搭建Struts2开发环境,从基础软件安装到配置web.xml和Struts2的Action,以及编写Struts2配置文件和JSP页面的创建。对于希望深入学习Struts2框架的读者,了解构建工具如Mave...

weixin_28922227的博客 1259

vue web-view引入网页内容

<template> <view> <web-view :src="url_"></web-view> </view> </view> </template> <script> export default { data() { return { url_:"http://xxx.com/privacy-policy.html" }; }, onL

userzou的博客 4240

通过CN3口直接控制台达伺服电机A2-M(二)

既然可以通过RS485与伺服驱动器进行通讯,那么就肯定可以控制转速 首先,需要了解下 ‘控制模式及控制命令输入源设定’ 依据以上资料,速度控制模式有两种,S和SZ模式,分别对应模式选择中的02和04,对P1-01的地址0102进行写地址操作即可实现,一开始我使用了S模式,但是这个模式在寸动模式下会自动运转,不符合我控制的要求,后面改用SZ模式,就可以实现零速度。 使用串口工具发送命令:“01 06 01 02 00 04 28 35”即可以实现设置,设置完成后可以手动在伺服驱动器的按键面板上进行确

HKing_evil的博客 6825

uniapp系列-超详细教你在uni-app+vue3里通过web-view组件传递信息打开H5页面写入localstorage并解决兼容性

如何使用web-view,并互相传递数据,使用web-view发送消息给H5,webview 给 uniapp发消息,@message无效怎么办?uniapp嵌套webview页面,接收数据onPostMessage写了不管用怎么办?或者@message写了不管用怎么办?(uniapp web-view @message不触发怎么办?)

tangdou369098655的博客 1万+

SAP HR模块配置假期日历和缺勤类型

SAP的HR模块。业务顾问在实施时一般会配置未来10年的假期日历,到期后再进行配置。同时,增加请假类型(缺勤信息类型)。记录这一过程。

福来阁86号技师的妖孽日常 5525

envi反演水质参数_遥感水质反演之反演模型

水质反演的框架图此为反演模型的章节第一部分,统计学基础:概率论、矩阵和数理统计的知识统计学知识框架# 1 基本统计概念知识在于应用,而非记忆!我们都是在样本的层面去操作数据的,以达到对总体性质的估计和推断,拿到一组数据首先进行基本的统计描述,常用的有:样本均值: 样本方差(调整方差)不是除以n,而是n-1, 标准差为样本方差开方即可皮尔逊积矩相关系数(简称相关系数): 相关系数范围在[-1,...

weixin_35275922的博客 3229

vue中调用webview实现和h5交互

【代码】vue中调用webview实现和h5交互。

guoruijun_2012_4的专栏 751

Unity FPS射击控制系统:数据驱动的武器行为解耦方案

在Unity第一人称射击(FPS)开发中,射击系统常因输入、状态、行为耦合导致连发异常、换弹冲突与网络同步失准。其本质是缺乏对‘武器行为’(如后坐力曲线、弹药逻辑)与‘射击控制’(如输入合法性校验、冷却调度)的正交分离。本方案基于ScriptableObject实现WeaponData数据资产化,配合ShootingController状态机服务,达成输入解耦、运行时参数可调、协程受控、网络预测友好等工程目标。适用于中大型FPS项目架构升级与数据驱动转型,尤其解决Unity InputSystem与物理反馈

weixin_30536861的博客 610

Vue 和 原生(webview)交互 解析

效果 项目地址 UIWebView与JS的深度交互 事情的起因还是因为项目需求驱动。折腾了两天,由于之前没有UIWebView与JS交互的经历,并且觉得这次在功能上有一定的创造性,特此留下一点文字,方便日后回顾。 参考 Github上看到了WebViewJavascriptBridge 这个用于UIWebView/WebViews和JS交互的封装库。 一开始,我

lhb_11的博客 2万+

基于粒子群优化的PID控制在药液流量控制系统中的应用

本文提出了一种基于粒子群优化(PSO)的PID控制算法,用于药液流量控制系统。系统采用C37控制器和Codesys 2.3编程环境实现,通过传感器实时监测流量、压力和车速,并控制水泵占空比和电动球阀开度来精确调节药液流量。硬件配置包括FT-2000流量传感器、PT-3000压力传感器和MV-500电动球阀等。控制算法将PSO与PID结合,使用ITAE指标优化PID参数,在Codesys中实现了包含PSO优化循环、PID控制等功能的程序模块。该系统通过分层控制策略和智能优化算法,提高了药液流量控制的精度和响应

AI的内部世界的博客 250

【WRF-Urban】使用 CGLC-MODIS-LCZ_100m 数据集运行 WRF 时的城市参数化问题

【WRF-Urban】使用 CGLC-MODIS-LCZ_100m 数据集运行 WRF 时的城市参数化问题

WW、forever的博客 711

Struts 2.0全攻略之Struts 2.0参考手册

附件是Struts 2.0全攻略之Struts 2.0参考手册chm,Share一下,有需要的请在下载后给评论下哈,Thanks!!

gaozzsoft的专栏 136

excel 如何自动调整行间距 vba

EXCEL是一个非常使用的软件,虽然我们平时仅使用他做一些报表,仅此而已;我在工作中,由于很懒,不愿意做考试重复的工作,就想着使用vba的宏来完成重复的工作,这样就能省出一部分的时间来了。本人不喜欢在博客里面写以下教程类的东西,我的理念是将工作中的痛点的解决办法分享出来,以解决问题为主。

sixtome 1316

struts2-jquery-plugin的使用全攻略

这是一个 Struts2 的插件,用来提供 Ajax 功能和基于 jQuery 的 UI部件。 插件下载:SpinnerTag - struts2-jquery - The Spinner widget renders a HTML spinner. - S

万维网 2284

第9.3章 从CMake基础到自动驾驶实战:构建跨平台C/C++项目的全能指南

《CMake构建实战:项目开发卷》精要指南 本文系统梳理了许宏旭《CMake构建实战》核心内容,涵盖C++构建全流程: 基础构建:详解MSVC/GCC编译器使用、Makefile编写及静态/动态库构建方法 CMake核心:解析语法结构、变量控制、文件操作等关键命令,阐述项目全生命周期管理 实战应用:通过快速排序、手写数字识别项目演示现代CMake实践,特别针对自动驾驶领域给出多传感器融合、SLAM等场景的CMake配置方案 特色价值:本书填补了官方文档实例不足的空白,提供300+代码示例,是掌握工业级C++

行知SLAM 1343

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Struts-2.1.6整合Tiles2全攻略

首先,我声明我用的是Struts-2.1.6而不是Struts-2.0.x,2.1和2.0是有些不同的,希望大家注意。下面进行配置步骤:1、导入包,把Struts-2.1.6文件夹lib里的jar包复制到项目文件WEB-INF/lib里,一共13个:1)struts2-core-2.1.6.jar2)xwork-2.1.2.jar3)freemarker-2.3.13.jar4

alex311的专栏 1056

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

struts 中中文处理全攻略

相信大家在进行web开发时经常会遇到中文处理的困惑。我们经常会发现web应用在处理英文时很正常,但是处理中文时却出现乱码现象。最郁闷的是部分乱码,部分又显示正常,搞得是不知所措。下面以我在一个实际项目中的经验,介绍如何在struts中处理中文。我采用的中文编码是utf8,相信对于gbk编码方式也大同小异。   1. 数据库表编码 那数据库表时采用utf8编码。如下: CREATE TABLE `p...

kaqi 165

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

【java技术面试第四十八讲】Java面试题48 . 说下struts2的执行流程或者struts2的原理...

Java面试题48 :说下struts2的执行流程或者struts2的原理提前预告,完全免费,写文不易: 如果喜欢、对你有所帮助还请大家点个在看, 好东西要大家共享才能实现它的价值 ,...

hello world! 340

在Struts2中实现自定义分页标签全攻略(一)

我们先看看这个分页标签的效果: 使用标签的最大好处就是下次再用到的话直接引用就行,而不必重写。 本人对Struts2自定义标签没有太深究,在网上找了一些资料可以参考参考: 其实,开发自定义标签并不需要Struts2的支持,一般情况下,只需要继承jav

Java高知社区 1万+

Gitlab密码重置全攻略:从命令行到安全加固建议

本文提供了GitLab管理员账户密码重置的完整解决方案,涵盖从命令行操作到安全加固的全过程。详细介绍了在Omnibus、Docker及Kubernetes等多种部署环境下,通过GitLab Rails控制台重置密码的具体步骤。同时,文章重点强调了重置后的关键安全措施,包括强制启用双因素认证(2FA)、强化密码策略、定期审计以及构建长期安全运维体系,旨在帮助团队从被动恢复转向主动防御,保障代码资产安全。

404

【java技术面试第五十一讲】Java面试题51 . 说一下SpringMVC和Struts2有什么不同

Java面试题51 :说一下SpringMVC和Struts2有什么不同提前预告,完全免费,写文不易: 如果喜欢、对你有所帮助还请大家点个在看, 好东西要大家共享才能实现它的价值 , ...

hello world! 256

小白也能看懂的-Java Web开发全攻略(超详细)

小白也能看懂的java-web开发攻略

m0_73978383的博客 1934

【java技术面试第四十九讲】Java面试题49 . Struts2的拦截器是什么

Java面试题49 :Struts2的拦截器是什么提前预告,完全免费,写文不易: 如果喜欢、对你有所帮助还请大家点个在看, 好东西要大家共享才能实现它的价值 , 让更多有需要的人看到,...

hello world! 365
上一篇: log4j在配置文件中对不同的包设定不同的LEVEL
下一篇: CVS在Linux中的配置和使用
tele
博客等级 码龄26年 1粉丝 12原创
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值