这一节,我们要掌握的东西
webwork操作session
webwork的验证
webwork两种驱动方式:
- Property-Driven
- Model-Driven
前面我们已经学会了webwork的第一个例子,我们发现webwork中的Action是完全和Sevlet解耦合的,在web开发中,我们很多时候都要对Session,Application,Parameter进行操作,那么在webwork中我们该怎么做呢?
我们可以通过两种方式对它们进行操作,一种是通过com.opensymphony.xwork.ActionContext进行操作,另外一种是通过实现com.opensymphony.webwork.interceptor.SessionAware接口,这一节我们只关注第一种方式
参考webwork的API,ActionContext是一个执行中的Action的上下文(Context),里面存放了Action,Session,Application,Parameter等信息,通过ActionContext我们就可以很方便的实现上述我们想要的功能啦!那么你可能会问ActionContext又是如何得到这些信息的呢?还记得上个教程中配置文件web.xml里的过滤器(filter)吗? 当一个浏览器产生一个请求到达webwork的时候,首先是被过滤器获得,过滤器通过询问com.opensymphony.webwork.dispatcher.mapper.ActionMapper接口,是否要响应这次请求(实际上就是看我们的配置文件里面是不是有这个action 名字),如果是,过滤器就负责把Session,Parameter,ServletContext等信息转化成一个map对象
然后在通过com.opensymphony.xwork.ActionProxyFactory 的createActionProxy(String namespace,String actionName, Map extraContext,boolean executeResult,boolean cleanupContext)创建ActinoProxy,注意它的参数,第一个是Action的名字空间,第一个是Action的名字,第三个map这里面就是包含的就是上面的信息了.通过ActionProxy,就已经解耦合了面向Servlet的webwork和xwork拉!
在ActionProxy通过一系列的方法之后会创建com.opensymphony.xwork.ActionInvocation接口,这个接口表示的是一次Action执行的状态,ActionContext实际上就是在这个接口的实现类DefaultActionInvocation被初始化的, 查看API,可以看到ActionInvocation有一个getInvocationContext()的方法,所以ActionContext就是这样来的
理论说了这么多,还是来点实际的吧:
类:
Domain Object: User
Action :SimpleAction
页面:
index.jsp
success.jsp
先看index.jsp
- <%@taglib prefix="ww" uri="/webwork" %>
- <html>
- <body>
- <form action="simple.action">
- <input type="text" name="user.username"><br>
- <input type="password" name="user.password"><br>
- <input type="submit" value="submit">
- </form>
- </body>
- </html>
和第一个教程是一样的,我就不再重复
User:
java 代码
- package mypackage;
-
- import java.util.ArrayList;
- import java.util.List;
-
- public class User {
- String username;
-
- String password;
-
- List message = new ArrayList();
-
- public List getMessage() {
- return message;
- }
-
- public void setMessage(List message) {
- this.message = message;
- }
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
- public String getUsername() {
- return username;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
- }
SimpleAction:
java 代码
- package mypackage;
-
- import java.util.Map;
- import com.opensymphony.xwork.Action;
- import com.opensymphony.xwork.ActionContext;
-
- public class SimpleAction implements Action {
-
- private User user = new User();
-
- public String execute() throws Exception {
- System.out.println(Thread.currentThread().getName());
- ActionContext context = ActionContext.getContext();
- Map session = context.getSession();
- session.put("user", user);
- user.getMessage().add("msg1");
- user.getMessage().add("msg2");
- user.getMessage().add("msg3");
- return SUCCESS;
- }
-
- public User getUser() {
- return user;
- }
-
- public void setUser(User user) {
- this.user = user;
- }
-
-
- }
其实代码比较简单
ActionContext通过静态方法返回自身的实例,然后可以看到context有很多方法,包括getApplication(),getSession(),getParameter(),它们返回的都是map.然后分别对这个map进行操作就可以拉
你可能会觉的奇怪,ActionContext通过一个简单的map如何区分两个不同的会话(Session)呢?
答案在于ActionContext是一个线程本地变量(thread local),webwork对于每一个不同的线程,都会把ActionContext放在他们的ThreadLocal中,而我们底层(Tomcat服务器,也是Servlet规范)对于每一个浏览器请求都会产生一个唯一的线程,这样一个线程对应一个浏览器会话,同时也对应了一个ActionContext.
我们可以给一个简单的Servlet 例子来帮助理解:
java 代码
- package mypackage;
-
- import java.io.IOException;
- import java.io.PrintWriter;
-
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- public class ThreadLocalServlet extends HttpServlet {
- public void service(HttpServletRequest request,HttpServletResponse response) throws IOException{
- response.setContentType("text/html");
- PrintWriter out = response.getWriter();
- out.println(Thread.currentThread().getName());
- }
- }
以下三个不同的浏览器窗口访问这个Servlet的一种结果:
http-8080-Processor24
http-8080-Processor25
http-8080-Processor26
webwork会通过三个不同的线程(同时对应了三个不同的浏览器窗口)产生三个不同的ActionContext实例 ,这样就起到了回话的作用了
好了,这个问题搞清楚之后,继续前面的的Action,
来看Action的配置文件xwork.xml
xml 代码
- <!---->>
- <xwork>
- <include file="webwork-default.xml" />
- <package name="default" extends="webwork-default">
- <action name="simple" class="mypackage.SimpleAction">
- <result name="success" type="redirect">success.jspresult>
- <interceptor-ref name="params" />
- action>
- package>
- xwork>
这个配置文件和上篇文件的配置文件是一样的
1.把默认webwork-default.xml包含在我们的配置文件里,webwork-default.xml放在webwork.jar文件中,里面定义了拦截器(inteceptor),和返回(result),这里是一个代码片段
- <!---->>
- <xwork>
- <package name="webwork-default">
- <result-types>
- ......
- <result-type name="dispatcher" class="com.opensymphony.webwork.dispatcher.ServletDispatcherResult" default="true"/>
- <result-type name="redirect" class="com.opensymphony.webwork.dispatcher.ServletRedirectResult"/>
- result-types>
- <interceptors>
- ......
- <interceptor name="params" class="com.opensymphony.xwork.interceptor.ParametersInterceptor"/>
- ......
- interceptors>
- <package name="webwork-default">
- xwork>
-
2.定义一个package,相当于java里面的的package关键字,起到一个命名空间的作用
3.在pakcage里面定义action,一个package里面可以定义多个action,这里主义的是name 要和 index.jsp 表单中action的名字相同。
4.在action中定义result,默认的返回方式(type)是dispater,我们把它改为重定向redirect
5.定义我们引用的 拦截器params
最后来看我们的success.jsp
xml 代码
- <%@taglib prefix="ww" uri="/webwork"%>
- <html>
- <body>
-
- <ww:property value="#session.user.username"/>
- <ww:property value="#session['user'].password"/>
- <ww:iterator value="#session.user.message">
- <div style="color: red"><ww:property/>div>
- ww:iterator>
-
- body>
- html>
-
-
1.声明了我们要使用的webwork标签库
2.通过
的形式,得到我们想要获取的值,
访问session可以通过两种方式
- #session.user.username
- #session['user'].password
我个人觉得第一种更简单一些。注意这样访问
- #session['user.password']
是得不到正确值的.
3.以下代码
- <ww:iterator value="#session.user.message">
- <div style="color: red"><ww:property/></div>
- </ww:iterator>
声明了一个迭代器标签它,它可以方便的取出一个容器里面的值,
ok,通过webwrok操作session就此结束,希望这篇文章能对您有所帮助,
还有很多的朋友在讲解webwork2,他们的教程比我写的更好
http://webwork.javascud.org/