显示标签为“Struts”的博文。显示所有博文
显示标签为“Struts”的博文。显示所有博文

2009年2月5日星期四

开始学习struts2(七)

好久没写了,过了个年,过了七天猪的日子,吃了睡睡了吃中间偶尔看看电视,为假期准备了几个电影都没看,唉:-(忙,上了几天班了,怎么感觉这周过的这么慢呢,刚刚刚周四
昨儿看了一集struts2

总结几点

1、struts.xml中的package标签有个abstract="true"属性,如果为true,则这个package中不能有<action>标签,为true表示这个package为一个抽象package,就像java中的接口中不能有方法实现似的。

2、package标签还有个namespace属性,它关系到这个package中的action访问路径,默认是"",比如

<package name= "capinfo" extends= "struts-default" namespace="/hello">
<action name= "HelloWorld"
class= "com.capinfo.struts2.action.HelloWordAction" >
<result>/HelloWorld.jsp</result>
</action>
</package>

则jsp中则应为<form action="/hello/HelloWorld.action" method="post">,如果没有找到hello/HelloWorld.action则会寻找namespace为""的,也就是HelloWorld.action,如果再没有,就会抛出异常。

3、在struts1中可以有多个struts-config.xml的文件,只要在web.xml配置org.apache.struts.action.ActionServlet时加到config参数中,以逗号分隔,在struts2中也可以有多个struts.xml形式的文件,这次不需要修改web.xml了,在struts.xml中添加诸如
<include file=""/>就Ok了

4、关于struts各种参数的配置信息位于struts2-core.jar/org.apache.struts2/default.properties中,如果要修改里面的配置,有两种方式,一是在struts.xml中配置,例如<constant name="struts.devMode" value="true" />,二是在classess中建一个struts.properties,在里面配置比如struts.i18n.encoding=GBK,在struts2-core.jar/org.apache.struts2/default.properties中有一下这句注释,说明了struts.properties将覆盖default.properties中的配置

### Struts default properties
###(can be overridden by a struts.properties file in the root of the classpath)
###

就总结这么些先。

2009年1月17日星期六

开始学习struts2(六)

前两天实践了关于拦截器的具体实现,说实话关于底层实现还没有看明白,看jdk的源码中的
public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces)
方法,好长啊
迂回一下,今儿看struts2的具体拦截器Interceptor怎么配置
配置可比自己写实现拦截器容易多了
1、首先写一个拦截器类,拦截器类有两只写法(目前俺知道的)
一种是显示com.opensymphony.xwork2.interceptor.Interceptor接 口,com.opensymphony.xwork2.interceptor.Interceptor接口有三个方法destroy()、init() 和String intercept(ActionInvocation actionInvocation),跟过滤器差不多
这里指出的是init初始化方法将在容器启动是调用这个方法。
package com.test.interceptor;

/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-15
* Time: 16:34:17
* To change this template use File | Settings | File Templates.
*/
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.ActionInvocation;

public class MyInterceptor implements Interceptor{

    public void destroy() {

    }

    public void init() {

    }

    public String intercept(ActionInvocation actionInvocation) throws Exception {

        System.out.println("test intercept begin");
        String result = actionInvocation.invoke();
        System.out.println("test intercept finish");
        return result;
    }
}
另一种就是继承com.opensymphony.xwork2.interceptor.AbstractInterceptor,这是个抽象类,并实 现了com.opensymphony.xwork2.interceptor.Interceptor接口,分别实现了init和destroy方法, 但什么都没做,继承AbstractInterceptor后,实现intercept方法就行了,
这里指出的是在intercept方法中执行actionInvocation.invoke();执行所拦截的action中的方法;
2、拦截器写完了剩下就是配置了,这里要用到struts.xml的组织结构<struts>中有<package>包的的概 念,包与包之间可以继承extends,就像子类继承父类一样,子类将拥有父类的属性和配置,我们一般都继承extends="struts- default",而struts-default定义在struts2-core.jar 中的struts-default.xml中,struts-default包中定义了很多struts2提供的拦截器和拦截器栈(拦截器栈可以包含多个 拦截器或拦截器栈),struts2的好多功能都是实现在这些拦截器中,其中有个<default-interceptor-ref name="defaultStack"/>标签定义了默认的拦截器,如果<action>配置中没有拦截器配置,那就调用默认拦截 器,如果有拦截器配置,要么同时加上默认拦截器,要么在自己的package中加入设置默认拦截器的标签。
<package name="capinfo" extends="struts-default">
        <interceptors>
            <interceptor name="myInterceptor" class="com.test.interceptor.MyInterceptor">
            </interceptor>
        </interceptors>
        <action name="HelloWorld"
            class="com.capinfo.struts2.action.HelloWordAction">
            <result>/HelloWorld.jsp</result>
            <interceptor-ref name="myInterceptor"></interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref>
        </action>

        <!-- Add your actions here -->
    </package>

2009年1月14日星期三

开始学习struts2(五)

说是struts2的核心就是拦截器
先看看拦截器的实现
实现拦截器有这么几个东西构成
1、目标对象-将被拦截的对象,这个对象中的方法被调用是将被拦截
要求目标对象面向接口编程,首先要定义接口package com.test.interceptor;

/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:37:23
* 面向接口编程
* 目标对象的接口
*/
public interface TargetInterface {
    public void doSomething();
}目标对象实现
package com.test.interceptor;

/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:36:26
* 目标对象
*/
public class Target implements TargetInterface{
    public void doSomething(){
        System.out.println("do something");
    }
}
2、拦截器对象-里面包含在调用目标对象前或后要调用的方法package com.test.interceptor;

/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:39:32
* 拦截器
*/
public class Interceptor {
    public void before(){
        System.out.println("before");
    }

    public void after(){
        System.out.println("after");
    }
}
3、处理器-处理器决定拦截器如何拦截目标对象
package com.test.interceptor;

/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:41:08
*/
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
* 处理器
* 在这里将目标对象Target和拦截器Interceptor联系在了一起
*/
public class MyHandler implements InvocationHandler{

    /**
     * 目标对象
     * 将来目标对象的方法将被注入interceptor
     */
    private Object object;

    /**
     * 拦截器
     * MyHandler负责将Interceptor这个拦截器注入到传入的目标对象object
     */
    private Interceptor interceptor = new Interceptor();

    public void setObject(Object object){
        this.object = object;
    }

    /**
     * 实现InvocationHandler接口的方法
     * @param o 在其上调用方法的代理实例
     * @param method 对应于在代理实例上调用的接口方法的 Method 实例
     * @param objects 包含传入代理实例上方法调用的参数值的对象数组
     * @return 从代理实例的方法调用返回的值
     * @throws Throwable
     */
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        Object result = null;
        interceptor.before();
        result = method.invoke(object,objects);
        interceptor.after();
        return result;
    }
}
4、代理对象-用于得到目标对象的代理对象
package com.test.interceptor;

/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:50:52
* 代理类
*/
import java.lang.reflect.Proxy;
public class MyProxy {
    /**
     * 返回obj的,处理器为MyHandler的代理对象
     * @param obj 目标对象
     * @return 目标对象的代理对象
     */
    public Object getProxy(Object obj){
        MyHandler myHandler = new MyHandler();
        myHandler.setObject(obj);
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(),myHandler);
    }
}
5、最后客户调用代码package com.test.interceptor;

/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:55:45
* 客户调用
*/
public class Client {
    public static void main(String[] args){
        //目标对象
        TargetInterface target = new Target();
        //代理对象
        MyProxy myProxy = new MyProxy();
        //通过代理对象得到目标对象的代理
        TargetInterface proxy = (TargetInterface)myProxy.getProxy(target);
        //通过目标对象的代理调用目标对象的方法
        proxy.doSomething();
    }
}

//输出:
//before
//do something
//after
将自己的理解写了注释,现在只理解到这个程度,像
Proxy.newProxyInstance
里面是怎么实现的,还没深入考究
继续努力

2009年1月8日星期四

开始学习struts2(四)

关于类型转换还有一种写法:public class ConverterPoint extends StrutsTypeConverter {

//    @Override
//    public Object convertValue(Map context, Object value, Class toType) {
//        if(Point.class == toType){
//            String[] params = (String[])value;
//            params = params[0].split(",");
//            Point point = new Point();
//            point.setX(Integer.parseInt(params[0]));
//            point.setY(Integer.parseInt(params[1]));
//            return point;
//           
//        }else if(String.class == toType){
//            Point point = (Point)value;
//            return "x=" + point.getX() + ",y=" + point.getY();
//        }
//        return super.convertValue(context, value, toType);
//    }

    @Override
    public Object convertFromString(Map arg0, String[] arg1, Class arg2) {
        String[] params = arg1;//(String[])value;
        params = params[0].split(",");
        Point point = new Point();
        point.setX(Integer.parseInt(params[0]));
        point.setY(Integer.parseInt(params[1]));
        return point;
    }

    @Override
    public String convertToString(Map arg0, Object arg1) {
        Point point = (Point)arg1;
        return "x=" + point.getX() + ",y=" + point.getY();
    }

   
}
原来是继承ognl.DefaultTypeConverter类,现在改成继承 org.apache.struts2.util.StrutsTypeConverter类了,看 org.apache.struts2.util.StrutsTypeConverter的源码可知道 org.apache.struts2.util.StrutsTypeConverter是个抽象类,并实现了 ognl.TypeConverter,org.apache.struts2.util.StrutsTypeConverter中有两个要实现的方法 一个convertFromString,一个convertToString,看方法名字就知道一个从字符串转换成Object,一个是将Object 转换成String,这样好像更加清晰

另外还有一种全局转换的配置,就是建立一个统一的属性文件,文件名为xwork-conversion.properties,与struts.xml位于统一目录下,里面的配置改成了
com.test.struts2.data.Point=com.test.struts2.action.ConverterPoint
意思是所有com.test.struts2.data.Point类型的对象都要通过com.test.struts2.action.ConverterPoint来转换

2009年1月5日星期一

开始学习struts2(三)

struts2局部类型转换

需求为:在页面的文本框输入一个x、y坐标,之间用","隔开,Action中有一个Point类型的属性,Point类里面有两个字段,分别是 x,y,int型,要求当页面提交时将文本框中的字符串转换成Point对象,当Action返回到页面时将Point转换成字符串显示

1、首先做一个jsp用于输入和提交:point.jsp

<s:form action="Converter">
<s:textfield name="point" label="Point"></s:textfield>
<s:textfield name="point.x" label="Point.X"></s:textfield>
<s:textfield name="point.y" label="Point.Y"></s:textfield>
<s:submit label="submit"></s:submit>
</s:form>

2、再建一个用于显示的jsp-converter.jsp

<body>
<s:property value="point"/><br>
<s:property value="point.x"/><br>
<s:property value="point.y"/><br>
</body>

3、Action类 ConverterAction

public class ConverterAction extends ActionSupport{

private Point point;

public Point getPoint() {
return point;
}

public void setPoint(Point point) {
this.point = point;
}

public String execute()throws Exception {
return "success";
}
}

4、struts.xml

<action name="Converter"
class="com.test.struts2.action.ConverterAction">
<result name="success">/converter.jsp</result>
<result name="input">/point.jsp</result>
</action>

5、转换类 ConverterPoint

public class ConverterPoint extends DefaultTypeConverter {

@Override
public Object convertValue(Map context, Object value, Class toType) {
if(Point.class == toType){
String[] params = (String[])value;
params = params[0].split(",");
Point point = new Point();
point.setX(Integer.parseInt(params[0]));
point.setY(Integer.parseInt(params[1]));
return point;

}else if(String.class == toType){
Point point = (Point)value;
return "x=" + point.getX() + ",y=" + point.getY();
}
return super.convertValue(context, value, toType);
}


}

6、配置转换
在ConverterAction 类的同一目录下定义属性文件ConverterAction-conversion.properties,注意文件 名,-conversion.properties为固定不变,ConverterAction为Action的名字,文件内容:

point=com.test.struts2.action.ConverterPoint

Ok了,这样就完工了

开始学习struts2(二)

前两天初步认识了一下struts2
今儿看来教程的第二三讲,搞清了一些前面的一些猜测或是疑问
1、struts2是不用<html:...>标签了,统一成了<s:...>
如下这样:
<s:form action="Converter">
<s:textfield name="point" label="Point"></s:textfield>
<s:submit label="submit"></s:submit>
</s:form>
显示效果:

注意到<s:textfield name="point" label="Point"></s:textfield>
中的label属性,它指定了文本框前面显示的内容,还自动加了冒号,哈哈,挺聪明的嘛,但是担心这样在复杂的页面设计中是不是好使。

哦对了,要想这么写,要在页面上方加上这个:<%@ taglib prefix="s" uri="/struts-tags" %>

2、Action
前面说的Action不再需要继承任何struts类,现在看来要失望了,为了方便起见还是建议集成ActionSupport类,目前觉得有用的是 ActionSupport中定义了几个static的result name,比如SUCCESS、ERROR,原来的return "success";现在可以写成return super.SUCCESS;,将标识用的字符串常量定义成static的是一直提倡的,还有就是validate()方法,验证有错误可以调用 addFieldError()方法,好像就是struts1 ActionForm里的东西,有所改进的是super.addFieldError("username", "username is null");将在页面中显示的效果为:错误信息"username is null"将在名字为"username"文本框的上面显示,这些如果能用ajax实现就好了。
对于Action解耦,可能在于它不再需要HttpServletRequest 、HttpServletResponse这样的容器运行时参数吧

2008年12月30日星期二

开始学习struts2

开始学习struts2今天第一次感觉到经济危机在我身边了,部门现在没有在做的项目了
经济危机中,赶紧为自己充充电,好到时候柳暗花明又一村,哈哈
学struts2
据说struts2基于webwork,基本上跟struts1没啥关系,如果有webwork的经验上手会很迅速
我没接触过webwork,就知道有这么个东西
今儿开始第一个struts
见过好多blog写有struts2的入门步骤,俺也写一个,为自己造个轮子,加深印象。
首先下载struts2的jar包,到http://struts.apache.org/,右上角有个struts2的链接,今天下到的是
struts2的2.0.14,昨天在javaeye上看到发布Struts2.1.3 发布了,只是主页还没看到,不止一次听大拿们说过不要追求新版本,哈哈
下载后的目录:app--struts的例子
              docs-doc文档
              lib-struts的jar包或依赖包
              src-源码
HelloWorld:

1、index.jsp
耳目一新的是,不需要用到struts html标签,这只是猜测,或许例子过于简单?今天工作中还感觉struts1的html标签真是不好用,想加个class、maxlength、size都不好使,让我很是郁闷。希望在继续学习中真的能耳目一新。
struts的action惯例后缀名改成了.action,不再像struts1的.do了,说是延续到webwork的惯例。
下面的页面代码submit的时候将提交到login.action
index.jsp
<body>
<form action="login.action" method="post">
      username:<input type="text" name="username"/>
      password:<input type="password" name="password"/>
      <input type="submit" value="submit"/>
</form>
</body>
2、Action类
struts2的Action可是大进步,不用再继承任何类,实现了松耦合,它好像将struts1的ActionForm融合了进来,据说 struts2不再用ActionForm,页面上对应的字段写在了Action中,struts2框架会自动调用get/set方法,在我印象里 struts1中的Action对象不是线程安全的,会在不同线程间重用,所以谨慎在里面定义字段,在这看来struts2的Action不是这样的,只 是猜测
package com.mystart.action;

public class LoginAction {

    private String username;
    private String password;
  
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
  
    public String execute() throws Exception{
        return "success";
    }
}

3、jsp、java类都定义了,现在要它们联系起来-struts配置文件
新的struts配置文件有个package包的概念,还没闹明白这个package的详细用法,有待继续深入
<action>标签有变化,type变成了class,path变成了name,struts1中name属性是制定ActionForm的,现在ActionForm没有了
forward变成了result,result的默认name=success

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">


<struts>
    <package name="struts" extends="struts-default">
        <action name="login" class="com.mystart.action.LoginAction">
            <result name="success">/result.jsp</result>
        </action>
    </package>

</struts>

4、最后启动struts2,配置web.xml
struts1的web.xml配置是放在<servlet>中,也就是是一个servlet
struts2变成了一个过滤器Filter
struts1中<url-pattern>被配置成拦截.do的链接
struts2变成了拦截所有链接 /*

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  
<filter>
      <filter-name>struts2</filter-name>
      <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

以上是驴了个struts的视频教程,今儿看了第一节课,看完后做了一下总结,里面有一些自己的理解,有不对的地方请兄弟们指正,别光光说我是猪,猪也要进步啊,嘿嘿,每一步都有疑问,明天带着问题接着看下一节,睡觉去。