Struts 2 讲义2.docx
- 文档编号:30236335
- 上传时间:2023-08-13
- 格式:DOCX
- 页数:28
- 大小:30.13KB
Struts 2 讲义2.docx
《Struts 2 讲义2.docx》由会员分享,可在线阅读,更多相关《Struts 2 讲义2.docx(28页珍藏版)》请在冰豆网上搜索。
Struts2讲义2
Struts2
(2)工作原理
一、Struts2框架结构
Struts2框架按照模块来划分,可以分为ServletFilters、Struts核心模块、拦截器和用户实现部分。
Struts2框架结构图如图4-1所示。
图4-1Struts2框架结构图
一个请求在Struts2框架中的处理大概分为以下几个步骤。
①客户端提交一个(HttpServletRequest)请求,如上文在浏览器中输入http:
//localhost:
8080/bookcode/ch2/Reg.action就是提交一个(HttpServletRequest)请求。
②请求被提交到一系列(主要是3层)的过滤器(Filter),如(ActionContextCleanUp、其他过滤器(SiteMesh等)、FilterDispatcher)。
注意:
这里是有顺序的,先ActionContextCleanUp,再其他过滤器(OthterFilters、SiteMesh等),最后到FilterDispatcher。
③FilterDispatcher是控制器的核心,就是MVC的Struts2实现中控制层(Controller)的核心。
④FilterDispatcher询问ActionMapper是否需要调用某个Action来处理这个(HttpServletRequest)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher则把请求的处理交给ActionProxy。
⑤ActionProxy通过ConfigurationManager(struts.xml)询问框架的配置文件,找到需要调用的Action类。
例如,用户注册示例将找到UserReg类。
⑥ActionProxy创建一个ActionInvocation实例,同时ActionInvocation通过代理模式调用Action。
但在调用之前,ActionInvocation会根据配置加载Action相关的所有Interceptor(拦截器)。
⑦一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果result。
Struts2的核心控制器是FilterDispatcher,有3个重要的方法:
destroy()、doFilter()和init()。
publicclassFilterDispatcherimplementsStrutsStatics,Filter{/**
*定义一个Log实例
*/
privatestaticfinalLogLOG=LogFactory.getLog(FilterDispatcher.class);
/**
*存放属性文件中的.STRUTS_I18N_ENCODING值
*/
privatestaticStringencoding;
/**
*定义ActionMapper实例
*/
privatestaticActionMapperactionMapper;
/**
*定义FilterConfig实例
*/
privateFilterConfigfilterConfig;
protectedDispatcherdispatcher;
/**
*创建一个默认的dispatcher,初始化filter
*设置默认的packages*
*/
publicvoidinit(FilterConfigfilterConfig)throwsServletException{
this.filterConfig=filterConfig;
dispatcher=createDispatcher(filterConfig);
dispatcher.init();
Stringparam=filterConfig.getInitParameter("packages");
Stringpackages="org.apache.struts2.statictemplateorg.apache.struts2.interceptor.debugging";
if(param!
=null){
packages=param+""+packages;
}
this.pathPrefixes=parse(packages);
}
//销毁filter方法
publicvoiddestroy(){
if(dispatcher==null){
LOG.warn("somethingisseriouslywrong,Dispatcherisnotinitialized(null)");
}else{
dispatcher.cleanup();
}
}
/**
*处理一个Action或者资源请求
*
*filter尝试将请求同actionmapping相匹配
*如果找到,将执行dispatcher的serviceAction方法
*如果Action处理失败,doFilter将建立一个异常
*
*如果请求静态资源
*资源将被直接复制给response
*
*如果找不到匹配Action或者静态资源,则直接跳出
publicvoiddoFilter(ServletRequestreq,ServletResponseres,FilterChainchain)throwsIOException,ServletException{
HttpServletRequestrequest=(HttpServletRequest)req;
HttpServletResponseresponse=(HttpServletResponse)res;
ServletContextservletContext=getServletContext();
StringtimerKey="FilterDispatcher_doFilter:
";
try{
UtilTimerStack.push(timerKey);
request=prepareDispatcherAndWrapRequest(request,response);
ActionMappingmapping;
try{
mapping=actionMapper.getMapping(request,dispatcher.getConfigurationManager());
}catch(Exceptionex){
LOG.error("errorgettingActionMapping",ex);
dispatcher.sendError(request,response,servletContext,HttpServletResponse.SC_INTERNAL_SERVER_ERROR,ex);
return;
}
if(mapping==null){
StringresourcePath=RequestUtils.getServletPath(request);
if("".equals(resourcePath)&&null!
=request.getPathInfo()){
resourcePath=request.getPathInfo();
}
if(serveStatic&&resourcePath.startsWith("/struts")){
Stringname=resourcePath.substring("/struts".length());
findStaticResource(name,request,response);
}else{
//为一个普通的request,则通过
chain.doFilter(request,response);
}
return;
}
/**
*这个方法询问ActionMapper是否需要调用某个Action来处理这个(request)请求,
*如果ActionMapper决定需要调用某个Action,
*FilterDispatcher则把请求的处理交给ActionProxy
dispatcher.serviceAction(request,response,servletContext,mapping);
}finally{
try{
ActionContextCleanUp.cleanUp(req);
}finally{
UtilTimerStack.pop(timerKey);
}
}
}
……
}
doFilter()方法中,将调用dispatcher.serviceAction,该方法如果找到相应的Action,将把用户请求交给ActionProxy。
serviceAction()代码在Dispatcher.java中。
Struts2用于处理用户请求的Action实例,并不是用户实现的业务控制器,而是Action代理。
【注】:
Action可以是一个普通的Java类,与ServletAPI完全分离,但是为了实现业务逻辑,Action需要使用HttpServletRequest内容。
Struts2设计的精巧之处就是使用了Action代理,Action代理可以根据系统的配置,加载一系列的拦截器,由拦截器将HttpServletRequest参数解析出来,传入Action。
同样,Action处理的结果也是通过拦截器传入HttpServletResponse,然后由HttpServletRequest传给用户。
其实,该处理过程是典型的AOP(面向切面编程)的方式。
Struts2处理过程模型如图4-2所示。
用户请求
【注】:
拦截器是Struts2框架的核心,通过拦截器,实现了AOP(面向切面编程)。
使用拦截器,可以简化Web开发中的某些应用,例如,权限拦截器可以简化Web应用中的权限检查。
二、业务控制器
业务控制器Action类是用户请求和业务逻辑之间的桥梁,是Struts2框架的核心组件,负责具体的业务逻辑处理。
对于开发者而言,主要的编写工作是编写action类。
Struts2中的Action类用来接收用户请求,然后调用模型组件去处理业务逻辑,最后返回一个字符串,Struts2框架会根据该字符串的值调用相应的页面显示。
Action类里通常包含了一个execute方法,当业务控制器处理完用户请求后,根据处理结果不同,返回不同字符串。
在Struts2中,Action可以以多种形式存在:
普通的Java类、实现Action接口和继承ActionSupport类。
1.普通的Java类
Action类可以是一个普通的Java类(POJO,PlainOrdinaryJavaObject),实现了与ServletAPI完全分离,这是Struts2的最大特点。
在该类中通常包含以下内容:
1无参数的execute()方法:
用于处理用户请求,返回一个与视图资源对应的字符串。
2成员变量及其setter和getter方法:
Action类中封装HTTP请求参数,程序通过成员变量的setter和getter方法来处理请求参数,因此成员变量的名称应该与HTTP请求参数的名称一致。
下面是一个Action类的例子:
【例1-1】编写一个普通的Action类:
UserReg1。
设计步骤:
1)修改已经成功的Strtus2项目,注意要修改项目中.mymetadata.MYMETADATA文件,修改部分主要有:
xmlversion="1.0"encoding="UTF-8"?
>
type="WEBname="userReg" id="myeclipse.1281676803203"context-root="/userReg" j2ee-spec="5.0"archive="userReg.war">
2)导入修改好的项目
3)编写Action类
packagereg.action;
importjava.util.Date;
//普通的Java类
publicclassUserReg1{
privateStringusername;//定义用户名
privateStringpassword1;//定义密码
//定义execute方法
publicStringexecute()
{
if(getPassword1().equals(getPassword2())&&!
(getUsername().trim().equals("")))
{
//将用户名存入session中
ActionContext.getContext().getSession().put("username",this.getUsername());
return"success";}
else
return"input";
}
}
当Action作为一个普通的Java类时,优点是无侵入,代码具有良好的复用性,无需与ServletAPI耦合,进行单元测试非常简单。
缺点是execute()方法返回的字符串没有进行规范,给配置文件和项目的管理带来了麻烦。
4)编写用户注册页面:
userReg1.jsp
用户注册
用户名:
密码:
确认密码:
5)结果页面
注册成功
欢迎propertyvalue="#session.username"/>注册!
propertyvalue="#session.username"/>注册!
6)struts.xml配置
2.实现Action接口
为了规范用户编写业务Action类,Struts2框架提供了一个名为“com.opensymphony.xwork2.Action”的接口,该接口提供了一个通用的规范。
开发人员在创建Action类时可以实现该接口,Action接口的源代码如下:
publicabstractinterfacecom.opensymphony.xwork2.Action{
//定义了常量
publicstaticfinaljava.lang.StringSUCCESS="success";
publicstaticfinaljava.lang.StringNONE="none";
publicstaticfinaljava.lang.StringERROR="error";
publicstaticfinaljava.lang.StringINPUT="input";
publicstaticfinaljava.lang.StringLOGIN="login";
//定义抽象方法
publicabstractjava.lang.Stringexecute()throwsjava.lang.Exception;
}
Action接口中定义了5个字符串常量,实现该接口,就可以返回5个规范的相应字符串。
【例1-2】编写一个实现Action接口的类:
UserReg2。
设计步骤:
1)编写用户注册界面,userReg2.jsp,与userReg1.jsp相似。
2)编写UserReg2.java实现Action接口
packagereg.action;
importjava.util.Date;
//实现了Action接口
publicclassUserReg2implementsAction{
privateStringusername;//定义用户名
privateStringpassword1;//定义密码
privateStringpassword2;//定义确认密码
//privateDatebirthday;//定义生日日期
//实现了Action接口中的execute方法,返回了Action接口中的字符串常量
publicStringexecute()
{
if(getPassword1().equals(getPassword2())&&!
(getUsername().trim().equals("")))
{
//将用户名存入session中
ActionContext.getContext().getSession().put("username",this.getUsername());
returnSUCCESS;
}
else
returnINPUT;
}
publicStringgetUsername(){
returnusername;
}
publicvoidsetUsername(Stringusername){
this.username=username;
}
当Action类实现Action接口时,优点是编写业务Action类更加规范,多人开发同一个项目时,使用Action接口提供的常量,项目的管理更加方便。
3)编写结果页面:
regResult2.jsp,同regResult2.jsp
4)编写配置文件:
struts.xml
3.继承ActionSupport类
Struts2除了提供Action接口外,还提供了一个名为“com.opensymphony.xwork2.Action-
Support”的工具类,该类已经实现了Action接口;除此之外,它还实现了:
●Validateable接口、
●ValidationAware接口、
●TextProvider接口
●LocalProvider接口,
提供了数据校验功能和访问国际化资源等方法。
通过继承该ActionSupport类,可以简化Struts2的Action开发。
【例1-3】编写一个继承ActionSupport类的Action类:
UserReg3。
设计步骤:
1)编写注册页面:
userReg3.jsp
<%@taglibprefix="s"uri="/struts-tags"%>
head/>
用户注册
formaction="userReg3"> textfieldname="username"label="用户名"/> passwordname="password1"label="密码"/> passwordname="password2"label="确认密码"/> submitvalue="确认"/> 2)编写UserReg3.java publicclassUserReg3extendsActionSupport{ privateStringusername;//定义用户名 privateStringpassword1;//定义密码 privateStringpassword2;//定义确认密码 publicStringgetUsername(){ returnusername; } publicvoidsetUsername(Stringusername){ this.username=username; } //定义execute方法 publicStringexecute(){ if(getPassword1().equals(getPassword2())&&! (getUsername().trim().equals(""))){ System.out.println("密码正确"); //将用户名存入session中 ActionContext.getContext().getSession().put("username",this.getUsername()); returnSUCCESS; } else returnINPUT; } //在validate()方法中进行验证 publicvoidvalidate(){ if(getUsername().equals("")){ addFieldError("username","必须输入用户名"); ActionSupport类中存在一个validate()方法,重写该方法可以实现输入验证。 如果校验表单输入域出现错误,则将错误添加到ActionSupport类的fieldErrors域中。 当Action类继承ActionSupport类时,优点是可在Action类中方便的使用ActionSupport类提供的各种方法,很大程度上简化了Action类的开发,提高了开发效率。 3)编写结果页面: regResult3.jsp同regResult1.jsp 4)配置struts.xml
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Struts 讲义2 讲义