在学习struts2之前,首先我们要明白使用struts2的目的是什么?它能给我们带来什么样的好处?
设计目标
1.Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。</br>
技术优势
Struts2有两方面的技术优势,一是所有的Struts2应用程序都是基于client/server HTTP交换协议,The Java Servlet API揭示了Java Servlet只是Java API的一个很小子集,这样我们可以在业务逻辑部分使用功能强大的Java语言进行程序设计。
二是提供了对MVC的一个清晰的实现,这一实现包含了很多参与对所以请求进行处理的关键组件,如:拦截器、OGNL表达式语言、堆栈。
下面,我们在深入剖析一下struts的工作原理。
原理图:(structs2核心控制器StrutsPrepareAndExecuteFilter)。老版本structs1是FilterDispatcher
工作原理:
在Struts2框架中的处理大概分为以下几个步骤** (这边官方说法有点啰嗦了,其实几句话就说明白了)**
1 客户端初始化一个指向Servlet容器(例如Tomcat)的请求
2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin)
3 接着StrutsPrepareAndExecuteFilte被调用,StrutsPrepareAndExecuteFilte询问ActionMapper来决定这个请是否需要调用某个Action
4 如果ActionMapper决定需要调用某个Action,StrutsPrepareAndExecuteFilter把请求的处理交给ActionProxy
5 ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类
6 ActionProxy创建一个ActionInvocation的实例。
7 ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper
流程图:
工作流程:
1、客户端浏览器发出HTTP请求.
2、根据web.xml配置,该请求被FilterDispatcher接收
3、根据struts.xml配置,找到需要调用的Action类和方法, 并通过IoC方式,将值注入给Aciton
4、Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。
5、Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并跳转到相应页面
6、返回HTTP响应到客户端浏览器
废话不多说,下面我们开始进入Structs2的学习吧!!!!!!!
一、建立第一个struts2的程序
a:找到struts目录下对应的apps目录
b:解压struts2-blank.war
c:copy对应的lib的jar文件
d:copy对应的struts.xml到src目录
e:注释掉struts.xml的多余内容
f:建立HelloStruts2.jsp文件
g:在struts.xml中照原配置进行对应的配置
h:修改对应的web.xml,建立Struts2的filter(参考struts自带的项目)
二、模块讲解
- Demo1讲解
<package name="default" namespace="/" extends="struts-default">
<action name="hello">
<result name="success">/hello.jsp</result>
</action>
(1)当你改<action name="hello">的name时,程序不能及时给反馈,需要重新启动
服务,这里有一个<constant name="struts.devMode" value="true" />
devMode-->develepment Mode 开发模式改为true
* Demo2讲解: namespace="/" 和访问的路径一一对应
>```
<constant name="struts.devMode" value="true" />
<package name="font" namespace="/font" extends="struts-default">
<action name="hello">
<result name="success">/hello.jsp</result>
</action>
(1)Namespace:决定了action的访问路径,默认为””,可以接收所有路径的action可以写为/,或者/XXX,或者/XXX/yyy,对应的action访问路径为/index.action,/XXX/index.action,/XXX/yyy/index.action.Namespace最好也用模块来命名
<package name="font".......><action name="hello">
A:这里的package name="",在java里可以建很多包,包下面可以建相同的类名。这里意思一样,当有两个action name都叫hello,这里可以写不同的 package name ,比如一个前台jspfont,后台backfont,下面action都叫hello,这样就不容易混乱了。
B:<result name="success"> 默认就是success可以不加
- Demo3讲解: Action问题
public class demoAction {
public String execute(){
return "shaca";
}
}
<action name="hello" class="com.aiyin.struts2.action.demoAction">
<result name="shaca">/index.jsp</result>
当action中有class时,这是会去到对应的类里面,找类里面的execute()方法,然后根据对应返回值“sucess”找到对应的jsp,然后再返回回来。。
当你没有配置class时,会默认走自己默认的class--->extends ActionSupport
implements Action
在企业开发只用extends ActionSupport
* Demo4讲解: 路径问题
>当没有对应的namespace,会返回到web.xml中丢给Tomcat去处理,会访问index.jsp
struts2中的路径问题是根据action的路径而不是jsp路径来路径,所以尽量不要使用相对路径。<a href="path/path.action">路径问题</a>
解决办法非常简单,统一使用绝对路径(在jsp中用request.getContextPath()方法拿到webapp路径)或者basePath
* Demo5讲解:Action执行的时候并不一定要执行execute()方法
> 可以在配置文件中配置Action的时候用method=来指定执行哪个方法。也可以在url 地址中动态指定(动态调用DMI) DynamicMethodInvocation
<action name="path" class="com.aiyin.struts2.action.demoAction" method="add">
动态调用 需要打开下面这个:
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<a href="path/user!add">添加用户</a>
* Demo6讲解:通配符
<package name="actions" namespace="/actions" extends="struts-default">
<action name="Student" class="com.aiyin.struts2.action.StudentAction" method="{1}">
<result>/Student{1}_success.jsp</result>
</action>
<action name="*" class="com.aiyin.struts2.action.{1}Action" method="{2}">
<result>/{1}{2}_success.jsp</result>
</action>
</package>
<a href="actions/Studentadd">添加学生</a><br />
* Demo7讲解:用Action的属性接收参数
//<a href="user/user!add?name=a&age=8">添加用户</a>
在类里面生成对应的name和age的get和set方法,会自动获取到
* Demo8讲解:简单数据验证
点击进入网页:[自定义Struts2表单验证后的错误信息显示格式](http://www.blogjava.net/lishunli/archive/2010/10/17/335384.html)
this.addFieldError("name", "name is error");
A:<s:fielderror cssStyle="color: red"></s:fielderror>
为什么报的错前面有小点:解压core jar包,template\simple下fielderror.ftl里有ul,所以我们可以自己重新定义它
B:<s:property value="errors.name[0]"></s:property>
<s:debug></s:debug>
C:使用Struts2验证框架实现输入校验
出现提示,window-->preferences-->catalog.关联xwork里的dtd
* Demo9讲解:访问Web元素
>方一手动获取:
取得request,session,application,HttpServletRequest,HttpServletResponse
HttpServletContext
方二:
implements RequestAware,SessionAware,ApplicationAware
private Map<String,Object> request;
private Map<String,Object> session;
private Map<String,Object> application;
// DI dependency injection
// Ioc inverse of control
public String execute(){
ServletActionContext.getRequest().setAttribute("name", name);
ActionContext.getContext().put("pass", pass);
request.put("r1","request2" );
session.put("s1","session2" );
application.put("a1","application2" );
return "success";
}
public void setApplication(Map<String, Object> application) {
this.application=application;
}
public void setSession(Map<String, Object> session) {
this.session=session;
}
public void setRequest(Map<String, Object> request) {
this.request=request;
}
jsp页面
>>${name} ${pass}
<%=request.getAttribute("r1") %>
<%=session.getAttribute("s1") %>
<%=application.getAttribute("a1") %><br />
<s:debug></s:debug><br />
ONGL<s:property value="#request.r1"/><br />
<s:property value="#session.s1"/><br />
<s:property value="#application.a1"/>
* 模块包含
```<include file="login.xml"></include>```
####三:result类型
result的目的就是告诉Struts2框架,在执行完一个Action后,需要系统做什么?
是把一个视图资源呈现给用户还是执行另外一个Action,result配置起到了一个“路标”的作用。
dispatcher:默认就是这个,用来转向页面,通常处理JSP
redirect:实际上dispatcher和redirect的区别就是在于转发和重定向的区别。
chain:用来处理Action链,可以forward跳到另外一个action
redirectAction:重定向到一个Action
<package name="resultTypes" namespace="/r" extends="struts-default">
<action name="r1">
<result type="dispatcher">/r1.jsp</result>
</action>
<action name="r2">
<result type="redirect">/r2.jsp</result>
</action>
<action name="r3">
<result type="chain">r1</result>
</action>
<action name="r4">
<result type="redirectAction">r2</result>
</action>
</package>
####四:通配符配置
在开发的过程中,有时候我们需要对于每个action配置一个error result页面,一般情况下,
这个error result页面都是同一个页面。如果在每一个action中单独配置error result的话就太麻烦了,
这时候我们就可以配置一个全局的result。这个全局的result在我们的包中,被所有的action共享,
但是不会被别的包共享
*struts.xml*
<package name="user" namespace="/user" extends="struts-default">
<global-results>
<result name="mianpage">/global.jsp</result>
</global-results>
<action name="user" class="com.aiyin.web.action.UserAction" >
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>
*Index.jsp*
<a href="user/user?type=1">返回success</a>
<a href="user/user?type=2">返回error</a>
<a href="user/user?type=3">返回global result</a>
*其他包如果也想用则可以继承user包*
<package name="admin" namespace="/admin" extends="user">
<action name="admin" class="com.aiyin.web.action.AdminAction" >
<result>/admin.jsp</result>
</action>
</package>
public String execute() {
return "mianpage";
}
网友评论