??xml version="1.0" encoding="utf-8" standalone="yes"?>
·ActionFormc?br> ·Struts自定义标?br> ·消息资源
其中QActionFormcLStruts框架的核心组件之一Q是Struts的关键视囄件?br>
1.ActionForm的作用机?br> ActionForm本质上是一UJavaBeanQ是专门用来传递数据的DTO(Data Transfer Object,数据传递对?。它包括用于表单数据验证的validate()Ҏ和用于数据复位的reset()Ҏ?br> Struts框架利用ActionForm对象来时存放视N面中的表单数据。例如一个登录页面会有一个用戯入框和一个密码输入框Q以及用来提交登录请求的按钮。当用户提交dh后,Struts用户名和密码两个输入域的数据自动填充到相应的ActionForm对象中,然后控制层可以从该ActionForm对象中读取用戯入的表单数据Q也可以把来自模型层的数据存攑ֈActionForm中,然后q回l视图显C?br>
ActionForm有请?request)和会?session)两种作用?scope)。如果ActionForm的作用域讑֮为requestQActionForm实例保存在request对象中,像其他保存在request对象中的属性一P仅在当前的请?响应范围内有效。如果ActionForm的作用域讑֮为sessionQ那么ActionForm实例被保存在session对象中,同一个ActionForm实例在整个HTTP会话中有效?br>
当验证ActionFormӞ如果到一个或多个验证错误QStruts框架会把错误转发回配|文件struts-config.xml?lt;action>元素的input属性所指定的输入页面?br>
2.ActionForm的用方?br>
(1)创徏ActionForm
可以通过扩展Struts软g包的ActionFormc,来创建具体的ActionForm。Struts软g包中的ActionFormcLw是一个抽象类Q在扩展该类Ӟ为每一个要从HTML表单中捕L输入域定义一个属性,使表单输入域与ActionForm的属性一一对应Q以使ActionForm能够捕获需要的表单输入。定义了具体的属性,可以覆写validate()和reset()ҎQ来实现具体的ActionForm验证规则和初始化Ҏ?br>
(2)配置ActionForm
每创Z个ActionFormc,需要在Struts的配|文件struts-config.xml中配|这个类Q例如:
<form-beans>
<form-bean name="loginActionForm" type="login.loginActionForm" />
</form-beans>
<form-beans>元素用来指定全体ActionForm的配|,一个Struts应用所有的ActionForm的配|都要位于该元素标记内?lt;form-beans>元素的子元素<form-bean>用来配置一个具体的ActionFormc,每个<form-bean>元素对应的内容ؓ一个form bean实例。一旦定义了<form-beans>元素Q就可以在Action中用它?br>
(3)讉KActionForm
ActionForm可以被JSPQStruts自定义标讎ͼAction或其他Weblg讉K。访问ActionForm的一般方法如下:
·使用Struts HTML标记?br> Struts HTML标记库提供了一l和ActionForm密切兌的标讎ͼq些标记对应到HTML表单域。如<html:form>标记对应HTML?lt;form>标记Q?lt;html:text>标记对应HTML表单的textcd<input>输入域。这些标记和ActionForm交互Q以把ActionForm中的属性值显C出来?br>
·从request或session对象中取出ActionForm对象
Ҏ作用域的不同QStruts框架把ActionForm实例保存在request或session对象中,保存旉用的keygؓ<form-bean>元素的名字,即name属性的倹{因此,可以像取ZQ何存攑֜request或session对象中的属性一样取出ActionForm实例。例如:
loginActionForm form=(loginActionForm)request.getAttribute("loginActionForm");
·在Actioncȝexecute()Ҏ中直接访问ActionForm
如果配置了ActionForm和Action映射QStruts框架׃把ActionForm作ؓ参数传递给Actioncȝexecute()ҎQ在execute()Ҏ中,可以直接d或设|ActionForm属性?br>
3.表单数据验证
表单验证是ActionForm的主要功能之一Q要实现q个功能Q我们需要采?个步骤:
·重写validate()Ҏ?br> ·在资源文件ApplicationResources.properties中设|可能的验证错误的标识?br> ·要在配置文gstruts-config.xml中,?lt;action>元素的validate属性设|ؓtrueQƈd<message-resources>元素以指明资源文件的存放路径?br> ·在相应输入页面的相应位置加如错误标记<html:errors>Q以输出可能的验证错误?br> (1)重写validate()Ҏ
对该form bean的validatet()Ҏq行重写。ActionErrorscd装了一l验证错误,它的用法cMMapcR而ActionMessagecd装了单个验证错误Q它的构造函数内的参数就指向资源文g内的一个错误文本。例如语?#8220;ActionMessage("login.password.error");”中的参数"login.password.error"其实是资源文gApplicationResources.properties中的一条错误文本的?key)。通过ActionErrors对象的add()ҎQ可以把ActionMessage对象加入到ActionErrors对象中?br> (2)讄资源文g
在Struts的资源文件ApplicationResources.properties中设|可能的验证错误的标识:
#用户名错?br>error.username.required=<li>Please input your username again!</li>
#密码错误
error.password.required=<li>Please input your password again!</li>
(3)修改配置文gstruts-config.xml
配|文件struts-config.xml?lt;action>元素的validate属性设定ؓtrue。此外,q需要增?lt;message-resource>元素Q以指明资源文g的\径?br> (4)在输入页面中加入错误标记
表单数据验证的目的是Q一旦用户在输入面表单中输入的数据不符合要求或出现错误QStruts验证机制把验证错误在该输入面相应的位|显C出来?br> <html:errors>是Struts的一个自定义标记。它能根据它的property属性从资源文gApplicationResources.properties中取出相应的验证错误Qƈ在输入页面中指定的位|显C验证错误?br>
HttpServletRequest request, HttpServletResponse response )
{
loginActionForm loginForm=(loginActionForm) actionForm;
//从form bean中取单数?br> String username=loginForm.getUsername();
String password=loginForm.getPassword();
//生成一个Session对象
HttpSession session=request.getSession(true);
session.removeAttribute("username");
session.setAttribute("username",username);
//生成一个ArrayList对象Qƈ把用户名和密码的值寸入该对象?br> ArrayList arr=new ArrayList();
arr.add(username);
arr.add(password);
String prompt;
//调用模型lgloginHandlerQ检查该用户是否已经注册
loginHandler login=new loginHandler();
boolean mark=login.checkLogin(arr);
if(mark) prompt="Success";
else prompt="Fail";
return actionMapping.findForward(prompt);
}
}
1.<form-beans>元素(用于描述ActionForm对象)
<form-beans>元素允许配置多个ActionFormcR它可包含零个或多个<form-bean>子元素?br> <form-bean>元素的主要属性如下:
·classNameQ可选,指定?lt;form-bean>元素对应的配|类Q默认gؓorg.apache.struts.config.FormBeanConfigQ自定义的配|类必须扩展该类?br> ·nameQ指定该ActionForm的唯一标识QStruts框架用该标识来引用这个form beanQ该属性必L定?br> ·typeQ指定ActionForm的完整类路径和类名,该属性必L定?br> 如果配置了动态ActionForm(DynaActionForm)Q则q必配|?lt;form-bean>元素?lt;form-property>子元素,用来指定表单字段?br>
2.<action-mappings>元素(用于描述Action对象)
<action-mappings>元素帮助q行框架内部的流E控Ӟ可将hURI映射到Actionc,Action对象与ActionForm对象相关联?br> <action-mappings>元素内可以定义多?lt;action>子元素?lt;action>元素所描述的是特定的请求\径和一个相应ActioncM间的映射关系。Struts控制器会请求中的URI路径与诸?lt;action>元素中的path属性相匚wQ以选出一个特定的映射?br> <action-mappings>元素的主?/span>属性如下:
·attributeQ设|和Action兌的forn bean在request/session内的属性keyQ通过request/session的getAttribute(attribute)Ҏq回该form bean的实例?br> ·nameQ指定同该Action兌的form bean的引用标识?br> ·typeQ指定该Actioncȝ完整c\径和cd?br> ·validateQ指定是否调用form bean的validate()Ҏ验证表单的数据,默认为true?br> ·inputQ指定表单输出页面的URL路径Q当表单验证p|时将h转发到该URL?br> ·scopeQ指定同该Actioncd联的forn bean的存在范_可选request和sessionQ默认ؓsession?br> ·pathQ指定Action的访问\径,卌Action在引用中的标识名Q以“/”开头?br> <action>元素中可包含零个或多?lt;forward>子元素,<forward>子元素定义了转发动作Q它的主要属性如下所C:
·nameQ指定{向标识名?br> ·pathQ指定{向标识名所对应的{向页面?br> ·redirectQ指定是转发q是重定向?br>
3.<global-forwardvs>元素
<global-forwards>元素用来定义在整个应用程序内的全局转发Q在该元素内可以定义多个<forward>子元素。例如:
<global-forwards>
<forward name="Success" path="/main.jsp"/>
<forward name="Fail" path="/register.jsp"/>
</global-forwards>
4.<message-resources>元素
<message-resources>元素用于配置消息资源文g(Resource Bundle),以在应用的客L界面中输出本地化消息文本。例如:
<mesasge-resources key="application" parameter="ApplicationResources"/>
该语句指定了一个叫ApplicationResources.properties的消息资源文件或属性文件?br> <message-resources>元素的属性如下:
·classNameQ指定和<form-bean>元素对应的配|类,默认gؓorg.apache.struts.config.MessageResourcesConfig
·factoryQ指定消息资源的工厂c,默认为org.apache.struts.uitl.PropertyMessageResourcesFactory
·keyQ指定资源文件存攑֜ServletContext对象中时使用的属性key,默认gؓGlobals.MESSAGE_KEY定义的字W串帔R?br> ·nullQ指定MessageResourcesҎ知消息的处理方式Q若为true返回空字符Ԍ若ؓfalse则返回类?/span>“???global.label.missing???”的字W串Q默认gؓtrue?br> ·parameterQ指定消息资源文件存攄路径?/span>
Bean的属性相兌?br> ·<bean:message>Q用于输出本地化的文本内容,它的key属性指定消息keyQ与消息key匚w的文本内Ҏ自于专门的Resource Bundle?br> ·<bean:write>Q用于输出JavaBean的属性倹{例如,<bean:write name="personbean" property="userName"/>Q它用于输出personbean对象的userName属性倹{?br> ·<logic:present>Q用来判断JavaBean在特定的范围内是否存在,只有当JavaBean存在Ӟ才会执行标签M中的内容,例如Q?br> <logic"present name="personbean" scope="request">
<h2>
Hello <bean:write name="personbean" property="userName"/>!<p>
</h2>
</logic:present>
<logic:present>标签用来判断在request范围内是否存在personBean对象Q如果存在,p出personBean的userName属性倹{与<logic:present>标签相对的是<logic:notPresent>标签Q它表示只有当JavaBean在特定的范围内部存在Ӟ才会执行标签能主体中的内宏V?/p>
2. q用Struts框架
·模型包括一个JavaBeanlgPersonBeanQ它有一个userName属性,代表用户输入的名字。它提供了get/setҎQ分别用于读取和讄userName属性,它还提供一个save()ҎQ负责把userName属性保存到持久化存储系l中Q如数据库或文gpȝ。对于更为复杂的Web应用QJavaBeanlg可以作ؓEJB或Web服务的前端组件?br> ·视图包括一个JSP文ghello.jspQ它提供用户界面Q接受用戯入的姓名。视图还包括一个ActionForm BeanQ它用来存放表单数据Qƈq行表单验证Q如果用h有输入姓名就提交表单Q将q回出错信息?nbsp;
·控制器包括一个ActioncHelloActionQ它完成三项dQ?Q进行业务逻辑验证Q如果用戯入的姓名?Monster", 返回错误消息;2Q调用模型组件PersonBean的save()ҎQ保存用戯入的名字Q?Q决定将合适的视图lgq回l用戗?br> ·除了创徏模型、视囑֒控制器组Ӟq需要创建Struts的配|文件struts-config.xmlQ它可以把这些组件组装v来,使它们协调工作。此外,q需要创建整个Web应用的配|文件web.xml?
3.创徏视图lg
本例中,视图包括两个lgQ?br> ·一个JSP文gQhello.jsp
·一个ActionForm BeanQ?HelloForm Bean (HelloForm.java)?br> 其中Qjsp中有代码<html:bean action="/HelloWorld" focus="userName">
当用h交了HTML表单后,Struts框架自动把表单数据l装到ActionForm Bean中。ActionForm Bean中的属性和HTML表单中的字段一一对应。ActionForm Beanq提供了数据验证ҎQ以及把属性重新设|ؓ默认值的Ҏ。Struts框架中定义的ActionFormcL抽象的,必须在应用中创徏它的子类Q来存放具体的HTML表单数据?br> HelloForm.java中有两个Ҏ的方法:
·validate()Q用于表单验证?br> ·reset()Q把属性重新设|ؓ默认倹{?br> 本例中的资源文g是application.propertiesQ用来存放数据信息?br>
4.创徏控制器组ӞHelloAction.java
控制器组件包括ActionServletcdActioncRActionServletcLStruts框架自带的,它是整个Struts框架的控制枢U,通常不需要扩展。Struts框架提供了可供扩展的Actionc,它用来处理特定的HTTPh?br> 所有的Actionc都是org.apache.struts.action.Action的子c,Action子类应该覆盖父类的execute()Ҏ?br>HelloAction.java的代码如下:
package hello;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.util.MessageResources;
import com.yourcompany.struts.PersonBean;
import com.yourcompany.struts.form.HelloForm;
/**
* @struts.action path="/hello" name="helloForm" input="/form/hello.jsp" scope="request" validate="true"
*/
public final class HelloAction extends Action {
/**
* Method execute
* @param mapping:ActionMapping包含了这个Action的配|信息和Struts-config.xml文g中的<action>元素对应?br> * @param form:ActionForm包含了用L表单数据Q当Struts框架调用execute()ҎӞActionForm中的数据
*已经通过了表单验证?br> * @param request:HttpServletRequest当前的HTTPh对象
* @param response:HttpServletResponse当前的HTTP响应对象
* @return ActionForward
*/
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception{
/* These "massage come from the ApplicationResources.properties file"
* getResources(HttpServletRequest request)Ҏq回当前默认的MessageResource对象Q它装了Resource
*Bundle 中的文本内容?nbsp;
* 接下来Actioncd可以通过MessageResource对象来访问文本内宏V例如:如果要读取消息key
*?hello.jsp.title"对应的文本内?可以调用MessageResourcescȝgetMessage(String key)Ҏ:
*String title=messages.getMessage("hello.jsp.title");
* MessageResources messages=getResources(request);
*/
/*
* Validate the request parameters specified by the user
* Note: Basic field validation done in HelloForm.java
* Business logic validation done in HelloAction.java
* 如果用户输入的姓名ؓ"Monster"Q将创徏包含错误信息的AcrionMessage对象QActionMessage对象被保?br> *到ActionMessages对象中。接下来调用在Action基类中定义的saveErrors()ҎQ它负责把ActionMessages
*对象保存到request范围内。最后返回ActionForward对象QStruts框架会根据ActionForward对象包含的{?br> *信息把请求{发到恰当的视囄Ӟ视图lg通过<html:errors>标签把request范围内的ActionMessages对象
*中包含的错误消息昄出来Q提C用户修攚w误?nbsp;
* */
ActionMessages errors=new ActionMessages();
String userName=(String)((HelloForm) form).getUserName();
String badUserName="Monster";
if(userName.equalsIgnoreCase(badUserName))
{
//equalsIgnoreCaseҎ同vequalsQ只不过equalsIgnoreCase 是忽略大写?br> errors.add("username",new ActionMessage("hello.dont.talk.to.monster",badUserName));
saveErrors(request,errors);
return (new ActionForward(mapping.getInput()));
}
/*
* HelloActioncdZ一个模型组件PersonBean对象Qƈ调用它的saveToPersistentStore()Ҏ来保存userName
*属性?br> * from the View,we now update the model
*
* */
PersonBean pb=new PersonBean();
pb.setUserName(userName);
pb.saveToPersistentStore();
/*
* 把PersonBean对象保存在request范围内内
* 从request范围内删除ActionForm Bean。由于后l的h转发目标lg不再需要HelloForm BeanQ所?br> *可将它删除。当HelloActionc调用HttpServletRequest的setAttribute()ҎQ向hello.jsp传递PersonBean对象Ӟ
*需要提供一个名?#8220;persinbean”的属性key:request..setAttribute("personbean",pb);
* hello.jsp通过q个名ؓ"personbean"的属性来dPersonBean对象Q?br> * <login:present name="personbean" scope="request">
* <h2>Hello <bean:write name="personbean" property="userName"/>!</h2>
* </logic:persent>
* 对于Struts应用Q提倡将q些属性key帔R定义在一个Java文gConstant.java中,例如本例?br> * */
request.setAttribute(com.yourcompany.struts.Constants.PERSON_KEY,pb);
request.removeAttribute(mapping.getAttribute());
return (mapping.findForward("SayHello"));
}
}
5.创徏模型lg
本例的模型组件是PersonBean.javaQPersonBean是一个非常简单的JavaBeanQ它包括一个userName属性,以及相关的get/setҎ。此外,它还有一个业务方法saveToPersistentStore()?br>
6. 创徏存放帔R的Java文gQConstant.java
7.创徏配置文gweb.xml和struts-config.xml
本例的运行流EؓQ?/span>
1.Servlet容器在web.xml文g中寻?lt;url-pattern>属性ؓ"*.do"?lt;servlet-mapping>元素Q?br> <servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
2.Servlet容器依据以上<servlet-mapping>元素?lt;servlet-name>属?action"Q在web.xml文g中寻扑配的<servlet>元素Q?br> <servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
</servlet>
3.Servlet容器把请求{发给以上<servlet>元素指定的ActionServletQActionServlet依据用户h路径"/HelloWorld"Q在Struts配置文g中检索path属性ؓ"/HelloWorld"的Action元素Q?br> <action
path="/HelloWorld"
type="hello.HelloAction"
name="HelloForm"
attribute="inputForm"
scope="request"
validate="true"
input="/hello.jsp"
>
<forward name="SayHello" path="/hello.jsp" />
</action>
4.ActionServletҎ<action>元素的name属性,创徏一个HelloForm对象Q把客户提交的表单数据传lHelloForm对象Q再把HelloForm对象保存?lt;action>元素的scope属性指定的request范围内?br>
5.׃<action>元素的validate属性ؓtrueQActionServlet调用HelloForm对象的validate()Ҏ执行表单验证?br>
·当文本框中不输入姓名的时?vallidate()Ҏq回一个ActionErrors对象?br> ActionServlet把HelloForm的validate()Ҏq回的ActionErrors对象保存在request范围?然后Ҏ<action>元素的input属?把客戯求{发给hello.jsp?br>
·当文本框中输入姓?Monster"的时?vallidate()Ҏq回ActionErrors对象中不包含MActionMessage对象,表示表单验证成功?br> ActionServlet查找HelloAction实例是否存在Q如果不存在创Z个实例,然后调用HelloAction的execute()Ҏ?br> HelloAction的execute()Ҏ先进行逻辑验证Q由于没有通过逻辑验证Q就创徏一个ActionMessage对象Q这个ActionMessage对象装了错误消息,execute()Ҏ把ActionMessage对象保存在ActionMessages对象中,再把ActionMessages对象存放在request范围内。最后返回一个ActionForward对象Q该对象包含的请求{发\径ؓ<action>元素的input属性指定的hello.jsp?br>
·当文本框中输入其他姓名的时?vallidate()Ҏq回ActionErrors对象中不包含MActionMessage对象,表示表单验证成功?br> HelloAction的execute()Ҏq行逻辑验证Q这ơ通过了验证,然后执行相关的业务逻辑Q最后调用ActionMapping.findForward()ҎQ参Cؓ“SayHello”:return (mapping.findForward("SayHello"));
ActionMapping.findForward()Ҏ?lt;action>元素中寻找name属性ؓ“SayHello”?lt;forward>子元素,然后q回与之对应的ActionForward对象Q它代表的请求{发\径ؓ“/hello.jsp”?br> HelloAction的execute()Ҏ把ActionForward对象q回lActionServletQActionServlet再把客户h转发lhello.jsp?br> hello.jsp?lt;bean:message>标签从Resource Bundle中读取文本,把它们输出到|页上,最后生成动态网c?br>
用JSP、Servlet及JavaBeans构徏一个简单的登陆pȝ。该pȝ的要求是Q当用户在登陆录面上填写用户名和密码ƈ提交之后Q系l将查该用户是否已经注册Q如果该用户已经注册Q系l将q入主页面,否则p入注册页面。我们将按照以下步骤构徏q个pȝQ?/p>
1.数据库设计:使用MS Access作ؓ数据库,构徏数据表T_UserInfo;
2.构徏视图lgQ登录页面login.jspQ主面main.jspQ以及注册页面register.jspQ?/p>
3.构徏控制层组Ӟ一个Servlet,取名为loginServlet.java;
4.构徏业务逻辑层组ӞModellgQ:一个JavaBeanQ取名ؓloginHandler.javaQ?/p>
5.构徏数据讉K层组Ӟ一个数据访问类Q取名ؓdbPool,java;
6.~译、打包程序;
7.部v该程序到Web服务器Tomcat中,然后q行?/p>
该系l的工作程如图Q?br>
1.数据库设?/p>
用户d是一个涉及数据库操作的用例。登录涉及的数据表名为testQ结构如下:
字段名:username 字段cdQnvarchar(50) 字段描述Q用户名Q主?/p>
字段名:password 字段cdQnvarchar(50) 字段描述Q密?/p>
2.构徏视图lg
本例?个视囄Ӟ分别是登录页面login.jspQ主面main.jsp及注册页面register.jsp。它们之间的关系是,当用户在d面login.jsp填上用户名和密码后ƈ提交后,pȝ检查用h否已l注册,如果该用户已l注册,pȝ进入主面main.jspQ否则就q入注册面register.jsp?/p>
当用h下login.jsp面上的“d”按钮后,pȝ把h传给一个叫做loginServlet的Servlet。以做进一步处理?br>
login.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<FORM name="form" action="loginservlet" method="get">
<P> 用户?
<INPUT type="text" name="username" size="15">
</P><P> ?amp;nbsp; ? <INPUT type="password" name="password" size="15">
</P><P>
<INPUT type="submit" name="submit" value="d"></P><P>
</P>
</FORM>
</body>
</html>
当用L录成功后Q系l{入main.jspQ告诉用户已l登录成功,现已q入主页面?br>
main.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'main.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
</head>
<body>
<h1>
<%=session.getAttribute("username")%>Q你成功dQ现已进入主面Q?br> </h1>
</body>
</html>
当用L录失败后Q系l{入register.jspQ告诉用L录失败,现已q入注册面Q请注册用户信息?br>
register.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'register.jsp' starting page</title>
</head>
<body>
<H1>
<%=session.getAttribute("username")%>Q你未能成功dQ现q入注册面Q请注册你的信息Q?br> </H1>
</body>
</html>
本例的控制器lg是一个ServletQ叫做loginServletQ该lg先处理HTTP POSThQ然后调用模型组件或业务逻辑lgloginHandler查该用户是否已注册,如果已注册,pȝ转入主页面main.jspQ否则进入注册页面register.jspQ要求用h册自q信息。另外,Servlet都要在web.xml中声明?br>
loginServlet.java:
package chap1;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class LoginServlet extends HttpServlet{
private static final long serialVersionUID = 2674925070582791853L;
//初始化Servlet
public void init() throws ServletException{
}
//处理HTTP POSTh
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
//从请求中取出用户名和密码的?br> String username=request.getParameter("username");
String password=request.getParameter("password");
//生成一个ArrayList对象Qƈ把用户名和密码的值存入该对象?br> ArrayList arr=new ArrayList();
arr.add(username);
arr.add(password);
//生成一个Session对象
HttpSession session=request.getSession(true);
session.removeAttribute("username");
session.setAttribute("username",username);
//调用模型lgloginHandler,查该用户是否已注?br> LoginHandler login=new LoginHandler();
boolean mark=login.checkLogin(arr);
//如果已经注册Q进入主面
if(mark) response.sendRedirect("main.jsp");
//如果未注册,q入注册面
else response.sendRedirect("register.jsp");
}
//处理HTTP GETh
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doPost(request,response);
}
//销毁Servlet
public void destroy(){
}
}
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee <servlet>
<servlet-name>loginservlet</servlet-name>
<servlet-class>chap1.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>loginservlet</servlet-name>
<url-pattern>/loginservlet</url-pattern>
</servlet-mapping>
</web-app>
本例的模型组Ӟ或称Z务逻辑lgQ是loginHandlerQ它先从数据讉KlgdbPool取得数据库连接,然后查数据库中是否已有该用户的记录,x查还用户是否已经注册。如果已注册Q返回trueQ否则返回false?br>
loginHandler.java:
package chap1;
import java.sql.*;
import java.util.*;
public class LoginHandler {
public LoginHandler() { }
Connection conn;
PreparedStatement ps;
ResultSet rs;
//查是否已注册
public boolean checkLogin(ArrayList arr)
{
//从数据访问组件dbPool中取得连?br> try{
conn=DbPool.getConnection();
String name=(String)arr.get(0);
String password=(String)arr.get(1);
String sql="select * from test where username=? and password=?";
ps=conn.prepareStatement(sql);
ps.setString(1,name);
ps.setString(2,password);
rs=ps.executeQuery();
if(rs.next()){
DbPool.dbClose(conn,ps,rs); //释放资源
return true;
}
else{
DbPool.dbClose(conn,ps,rs);
return false;
}
}catch(SQLException e){
System.out.print("SQLException"+e.getMessage());
return false;
}
}
}
本例的数据库讉Klg是dbPoolQdbPool从一个属性文件db.properties中获得数据库驱动E序QURLQ用户名和密码,然后利用q些信息q接一数据库,取得q接。因为所用数据库是SQL ServerQ数据库驱动E序采用com.microsoft.jdbc.sqlserver.SQLServerDriverQ数据库URL为jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=test;本例需要把数据库驱动程序(3个jar包)攑֜lib目录下?br>
DbPool.java:
package chap1;
import java.io.*;
import java.util.*;
import java.sql.*;
public class DbPool {
private static DbPool instance=null;
//取得q接
public static synchronized Connection getConnection(){ //多线E?
if(instance == null){
instance = new DbPool();
}
return instance._getConnection();
}
private DbPool()
{
super();
}
private Connection _getConnection(){
try{
String sDBDriver=null;
String sConnection=null;
String sUser=null;
String sPassword=null;
Properties p=new Properties();
InputStream is=getClass().getResourceAsStream("/db.properties");
p.load(is);
sDBDriver=p.getProperty("DBDriver",sDBDriver);
sConnection=p.getProperty("Connection",sConnection);
sUser=p.getProperty("User",sUser);
sPassword=p.getProperty("Password",sPassword);
Properties pr=new Properties();
pr.put("user",sUser);
pr.put("password",sPassword);
pr.put("characterEncoding","GB2312");
pr.put("userUnicode","TRUE");
Class.forName(sDBDriver).newInstance();
return DriverManager.getConnection(sConnection, pr);
}
catch(Exception se){
System.out.println(se.getMessage());
return null;
}
}
//释放资源
public static void dbClose(Connection conn,PreparedStatement ps,ResultSet rs)
throws SQLException
{
rs.close();
ps.close();
conn.close();
}
}
db.properties:
DBDriver=com.microsoft.jdbc.sqlserver.SQLServerDriver
Connection=jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=test;
User=sa
Password=sa
~译loginServlet.javaӞ需要引用javax.servlet和javax.servlet.http两个软g包。Sun的JDK一般不包含q两个Y件包。这两个软g包包含在servlet.jar中。因此在~译servletӞ需要引用servlet.jar。假如servlet.jar攑֜d:\library目录中,servletE序攑֜d:\login目录中,要用javac~译servletE序Q则~译命o如下Q?br>D:\javac -classpath "d:\library\servlet.jar" login\*.java
在实际的q行中,有一些细节是需要注意的Q我jsp文g攑֜了一个文件夹jsp中,所以遇C一些问题:
1.jsp面中action属性是与url-pattern对应的,E序首先与url-pattern对应Q然后通过映射扑ֈ实际的servletcR?br>2.jsp面中action属性内容中如果含有“/”Q例如:action="/login"Q则pȝ在webapps目录下开始查扑֯应的servletc,如果不含有,则从本工E目录下查找servletcR?nbsp;
package chap1;
import java.sql.*;
public class JdbcTest {
public static void main(String[] args) {
try{
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost/test";
Connection con=DriverManager.getConnection(url,"root","root");
String sql="select * from test where userid=?";
PreparedStatement ps=con.prepareStatement(sql);
ps.setString(1,"123");
ResultSet rs=ps.executeQuery();
while(rs.next()){
String name=rs.getString("username");
int age=rs.getInt(3); //q里?#8220;3”指数据表中的W?个字D늚?br> System.out.println(name);
System.out.println(age);
}
rs.close();
con.close();
}catch(SQLException e){
System.out.println("Error"+e);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
MyFirstServlet.java:
package chap1;
import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;
import java.util.*;
public class MyFirstServlet extends HttpServlet{
public void doPost(HttpServletRequest request,HttpServletResponse response){
String name=request.getParameter("username");
RequestDispatcher rd;
try{
try{
if(name.equals("Tom")){
HttpSession session=request.getSession(true);
session.setAttribute("nm",name);
response.sendRedirect("servlet/reply.jsp");
}
else{
rd=request.getRequestDispatcher("servlet/error.jsp");
rd.forward(request,response);
}
}catch(ServletException e){System.out.println(e);}
}catch(IOException e){System.out.println(e);}
}
public void doGet(HttpServletRequest request,HttpServletResponse response){
doPost(request,response);
}
}
在Java Web应用E序中,Servlet常用做控制器lg。当Servlet部v到Web服务器中Ӟ需要Web配置文gWeb.xml中进行声明?br><servlet>
<servlet-name>MyFirstServlet</servlet-name>
<servlet-class>chap1.MyFirstServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyFirstServlet</servlet-name>
<url-pattern>/MyFirstServlet</url-pattern>
</servlet-mapping>