2011年11月30日

(转贴)数据库连接(内连接,外连接,交叉连接)

数据库连接分为:内连接,外连接(左、右连接,全连接),交叉连接
文章地址 : http://www.zxbc.cn/html/20080527/51189.html
转载 
内连接:把两个表中数据对应的数据查出来 
外连接:以某个表为基础把对应数据查出来(全连接是以多个表为基础) 
student表 
no name 
1     a 
2     b 
3     c 
4     d 
grade表 
no grade 
1     90 
2     98 
3     95 
内连接 inner join(查找条件中对应的数据,no4没有数据不列出来) 
语法:select * from student inner join grade on student.no = grade.no 
结果 
student.no name grade.no grade 
1             a             1         90 
2             b             2         98 
3             c             3         95 
左连接(左表中所有数据,右表中对应数据) 
语法:select * from student left join grade on student.no = grade.no 
结果: 
student.no name grade.no grade 
1                 a         1         90 
2                 b         2         98 
3                 c         3         95 
4                 d     
右连接(右表中所有数据,左表中对应数据) 
语法:select * from student right join grade on student.no = grade.no 
结果: 
student.no name grade.no grade 
1                 a         1         90 
2                 b         2         98 
3                 c         3         95 
全连接 
语法:select * from student full join grade on student.no = grade.no 
结果: 
no name grade 
1     a     90 
2     b     98 
3     c     95 
4     d 
1     a     90 
2     b     98 
3     c     95 
注:access 中不能直接使用full join ,需要使用union all 将左连接和右连接合并后才可以

交叉连接
将两个表所有行组合,连接后的行数为两个表行数的乘积(笛卡尔积)
语法,借用上面的例子应该是
select * from student cross join grade

行数应该为12行 :
no name grade 
1     a     90 
2     b     98 
3     c     95 
4     d  
1     a     90 
2     b     98 
3     c     95 
4     d 
1     a     90 
2     b     98 
3     c     95 
4     d 

posted @ 2011-11-30 17:24 AK47 阅读(475) | 评论 (0)编辑 收藏

2011年11月23日

JAXB向Xml非根节点添加一个或多个属性

JAXB 向Xml非根节点添加一个或多个属性,直接上代码,关于JAXB的相关注解可查阅JAVA API。

原创文章,转载请注明出处。http://www.blogjava.net/kangdy/archive/2011/11/23/364635.html

code1: colors类  根节点
code1
package com.kangdy.test;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Colors")
@XmlAccessorType(XmlAccessType.FIELD)
public class Colors {
    
    @XmlElement(name = "red",nillable=true)
    private Red red;
    
    @XmlElement(name = "blue",nillable=true)
    private Blue blue;

    public Red getRed() {
        return red;
    }

    public Blue getBlue() {
        return blue;
    }

    public void setRed(Red red) {
        this.red = red;
    }

    public void setBlue(Blue blue) {
        this.blue = blue;
    }
}

code2:  Red类  子节点
code2package com.kangdy.test;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "red")
@XmlAccessorType(XmlAccessType.FIELD)
public class Red {
    
    private String value;
    
    @XmlAttribute(name = "att1")
    private String att;
    
    public String getValue() {
        return value;
    }
    
    public void setValue(String value) {
        this.value = value;
    }

    public String getAtt() {
        return att;
    }

    public void setAtt(String att) {
        this.att = att;
    }
    
}


code3:  类 Blue 子节点
code3
package com.kangdy.test;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "blue")
@XmlAccessorType(XmlAccessType.FIELD)
public class Blue {
    private String value;
    
    @XmlAttribute(name = "att2")
    private String att2;
    
    @XmlAttribute(name = "att1")
    private String att;
    
    public String getAtt() {
        return att;
    }

    public void setAtt(String att) {
        this.att = att;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getAtt2() {
        return att2;
    }

    public void setAtt2(String att2) {
        this.att2 = att2;
    }
}

code4: main类
code4
package com.kangdy.test;

import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class Jaxbtest {
    public static void main(String[] args) throws Exception {

        StringWriter writer = new StringWriter();
        JAXBContext jc = JAXBContext.newInstance(Colors.class);
        Marshaller ma = jc.createMarshaller();
        ma.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        
        Colors colors = new Colors();
        Red red = new Red();
        red.setAtt("att-red");
        red.setValue("red");
        Blue blue = new Blue();
        blue.setValue("blue");
        blue.setAtt("att-blue");
        blue.setAtt2("blue-att2");
        colors.setRed(red);
        colors.setBlue(blue);
        
        ma.marshal(colors, writer);
        System.out.println(writer.toString());

    }
}

运行结果:
结果
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Colors>
    <red att1="att-red">
        <value>red</value>
    </red>
    <blue att1="att-blue" att2="blue-att2">
        <value>blue</value>
    </blue>
</Colors>

posted @ 2011-11-23 14:33 AK47 阅读(10080) | 评论 (4)编辑 收藏

2011年11月16日

(转载)关于paramsPrepareParamsStack

原帖地址:
http://hi.baidu.com/%CC%AB%C6%BD%D1%F31986/blog/item/110b13b1384e805e08230259.html
转贴

paramsPrepareParamsStack在Struts 2.0中是一个很奇妙的interceptor stack,以至于很多人疑问为何不将其设置为默认的interceptor stack。paramsPrepareParamsStack主要解决了ModelDriven和Preparable的配合问题,从字面上理解来说, 这个stack的拦截器调用的顺序为:首先params,然后prepare,接下来modelDriven,最后再params。Struts 2.0的设计上要求modelDriven在params之前调用,而业务中prepare要负责准备model,准备model又需要参数,这就需要在 prepare之前运行params拦截器设置相关参数,这个也就是创建paramsPrepareParamsStack的原因。流程如下:
   1. params拦截器首先给action中的相关参数赋值,如id  
   2. prepare拦截器执行prepare方法,prepare方法中会根据参数,如id,去调用业务逻辑,设置model对象
   3. modelDriven拦截器将model对象压入value stack,这里的model对象就是在prepare中创建的
   4. params拦截器再将参数赋值给model对象
   5. action的业务逻辑执行 依据此stack,一个action的代码通常如下

public class UserAction extends ActionSupport implements ModelDriven, Preparable {
    private User user;
    private int id;
    private UserService service; // user business service

    public void setId(int id) {
        this.id = id;
    }

    /**
     * create a new user if none exists, otherwise load the user with the
     * specified id
     */
    public void prepare() throws Exception {
        if (id == 0) {
            user = new User();
        } else {
            user = service.findUserById(id);
        }
    }

    public Object getModel() {
        return user;
    }

    /**
     * create or update the user and then view the created user
     */
    public String update() {
        if (id == 0) {
            service.create(user);
        } else {
            service.update(user);
        }
        return "redirect";
    }

    /**
     * delete the user and go to a default home page
     */
    public String delete() {
        service.deleteById(id);
        return "home";
    }

    /**
     * show the page allowing the user to view the existing data
     */
    public String view() {
        return "view";
    }

    /**
     * show the page allowing the user to view the existing data and change the
     * values
     */
    public String edit() {
        return "input";
    }

在上述代码中,edit和view都不需要根据id再为界面准备数据,因为prepare方法已经准备好了model,这些方法很简单。对于update 方法,prepare首先会从数据库中加载数据,然后params拦截器会将参数值付给model,在update直接更新就可以,不会出现数据被乱更新 的情况。象Hibernate框架,会判断哪些字段更新了,然后进行更新,性能也不会损失。
通过paramsPrepareParamsStack可以让流程更明确,代码更简洁,也更利于大家的交流。

posted @ 2011-11-16 15:39 AK47 阅读(425) | 评论 (0)编辑 收藏

2011年11月11日

(转载) Struts 2杂谈(1):ValueStack对象的传送带机制

Struts 2杂谈(1):ValueStack对象的传送带机
作者:nokiaguy  原文地址:http://blog.csdn.net/nokiaguy/article/details/4684750
转贴
   众所周知,Strut 2的Action类通过属性可以获得所有相关的值,如请求参数、Action配置参数、向其他Action传递属性值(通过chain结果)等等。要获得 这些参数值,我们要做的唯一一件事就是在Action类中声明与参数同名的属性,在Struts 2调用Action类的Action方法(默认是execute方法)之前,就会为相应的Action属性赋值。
    要完成这个功能,有很大程度上,Struts 2要依赖于ValueStack对象。这个对象贯穿整个Action的生命周期(每个Action类的对象实例会拥有一个ValueStack对象)。当 Struts 2接收到一个.action的请求后,会先建立Action类的对象实例,并且将Action类的对象实例压入ValueStack对象中(实际 上,ValueStack对于相当一个栈),而ValueStack类的setValue和findValue方法可以设置和获得Action对象的属性 值。Struts 2中的某些拦截器正是通过ValueStack类的setValue方法来修改Action类的属性值的。如params拦截器用于将请求参数值映射到相 应成Action类的属性值。在params拦截器中在获得请求参数值后,会使用setValue方法设置相应的Action类的属性。
    从这一点可以看出,ValueStack对象就象一个传送带,当客户端请求.action时,Struts 2在创建相应用Action对象后就将Action对象放到了ValueStack传送带上,然后ValueStack传送带会带着Action对象经过 若干拦截器,在每一拦截器中都可以通过ValueStack对象设置和获得Action对象中的属性值。实际上,这些拦截器就相当于流水线作业。如果要对 Action对象进行某项加工,再加一个拦截器即可,当不需要进行这项工作时,直接将该拦截器去掉即可。
    下面我们使用一个例子来演示这个过程。在这个例子中实现了一个拦截器,该拦截器的功能是将一个属性文件中的key-value对映射成相应的属性的值。如下面是一个属性文件的内容:

    name = 超人
    price = 10000

    我们可以在Action类中定义name和price属性,在Action中引用这个拦截器后,就会自动为属性赋值。
    在使用该拦截器有如下规则:
    1.  拦截器读取的属性文件路径由path参数指定。
    2.  属性文件的编码格式由encoding参数指定,默认值是UTF-8。
    3.  如果某个key中包含有“.”(该符号不能出现在标识符中),则有如下处理方法:
    (1)将Action类的属性名定义为去掉“.”的key。例如,key为person.name,而属性名可定义为personname。
    (2)将Action类的属性名定义为将“.”替换成其他字符的表示符号。例如,key为person.name,而属性名可定义为person_name,其中“_”由separator参数指定。
    4.  如果key太长,也可以直接使用Action参数进行映射,例如,key为country.person.name,可做如下映射:
      <param name="countrypersonname">name</param>
      要注意的是,name属性值不能包含“.”,因此,应将key值中的“.”去掉。现在就可以直接在Action类中定义名为name的属性的,name属性的值会与key值相同。
    5.  上面所有的规则可以同时使用。

拦截器的源代码:

package interceptors;

import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
import java.io.InputStream;
import java.io.FileInputStream;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.util.ValueStack;

public class PropertyInterceptor extends AbstractInterceptor
{
    
private static final String DEFAULT_PATH_KEY = "path";
    
private static final String DEFAULT_ENCODING_KEY = "encoding";
    
private static final String DEFAULT_SEPARATOR_KEY = "separator";

    
protected String pathKey = DEFAULT_PATH_KEY;
    
protected String encodingKey = DEFAULT_ENCODING_KEY;
    
protected String separatorKey = DEFAULT_SEPARATOR_KEY;

    
public void setPathKey(String pathKey) 
    {
        
this.pathKey = pathKey;
    }

    
public void setEncodingKey(String encodingKey)
    {
        
this.encodingKey = encodingKey;
    }

    
public void setSeparatorKey(String separatorKey)
    {
        
this.separatorKey = separatorKey;
    }

    @Override
    
public String intercept(ActionInvocation invocation) throws Exception
    {
        ActionConfig config 
= invocation.getProxy().getConfig();

        Map
<String, String> parameters = config.getParams();
        
if (parameters.containsKey(pathKey))
        {
            String path 
= parameters.get(pathKey);
            String encoding 
= parameters.get(encodingKey);
            String separator 
= parameters.get(separatorKey);
            
if (encoding == null)
                encoding 
= "UTF-8";
            
if (separator == null)
                separator 
= "";
            path 
= invocation.getAction().getClass().getResource(path)
                    .getPath();
            Properties properties 
= new Properties();
            InputStream is 
= new FileInputStream(path);
            java.io.Reader reader 
= new java.io.InputStreamReader(is, encoding);
            
            properties.load(reader);
            ActionContext ac 
= invocation.getInvocationContext();
            ValueStack stack 
= ac.getValueStack();
            System.out.println(stack.hashCode());
            Enumeration names 
= properties.propertyNames();
            
while (names.hasMoreElements())
            {
                
//  下面会使用setValue方法修改ValueStack对象中的相应属性值
                String name = names.nextElement().toString();
                
if (!name.contains("."))
                    stack.setValue(name, properties.get(name)); 

                String newName 
= null;
                newName 
= parameters.get(name.replaceAll("//."""));
                
if (newName != null)
                    stack.setValue(newName, properties.get(name));

                
if (!separator.equals(""))
                {
                    newName 
= name.replaceAll("//.""");
                    stack.setValue(newName, properties.get(name));
                }               
                newName 
= name.replaceAll("//.", separator);
                stack.setValue(newName, properties.get(name));
            } 
        }
        
return invocation.invoke();
    }
}

用于测试的Action类的源代码:

package actions;

public class MyAction
{
    
private String name;
    
private Integer price;
    
private String log4jappenderstdout;
    
private String log4j_rootLogger;
    
private String conversionPattern;

    
public String getName()
    {
        
return name;
    }

    
public void setName(String name)
    {
        
this.name = name;
    }

    
public Integer getPrice()
    {
        
return price;
    }

    
public void setPrice(Integer price)
    {
        
this.price = price;
    }

    
public String getLog4jappenderstdout()
    {
        
return log4jappenderstdout;
    }

    
public void setLog4jappenderstdout(String log4jappenderstdout)
    {
        
this.log4jappenderstdout = log4jappenderstdout;
    }

    
public String getLog4j_rootLogger()
    {
        
return log4j_rootLogger;
    }

    
public void setLog4j_rootLogger(String log4j_rootLogger)
    {
        
this.log4j_rootLogger = log4j_rootLogger;
    }

    
public String getConversionPattern()
    {
        
return conversionPattern;
    }

    
public void setConversionPattern(String conversionPattern)
    {
        
this.conversionPattern = conversionPattern;
    }

    
public String execute()
    {
        System.out.println(
"name:" + name);
        System.out.println(
"price:" + price);
        System.out.println(
"log4jappenderstdout:" + log4jappenderstdout);
        System.out.println(
"log4j_rootLogger:" + log4j_rootLogger);
        System.out.println(
"conversionPattern:" + conversionPattern);
        
return null;
    }
}

Action类的配置代码如:

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

        
<interceptors>
            
<interceptor name="property"
                class
="interceptors.PropertyInterceptor" />
            
<interceptor-stack name="myStack">
                
<interceptor-ref name="defaultStack" />
                
<interceptor-ref name="property" />
            
</interceptor-stack>
        
</interceptors>
        
<action name="test" class="actions.MyAction">
            
<interceptor-ref name="myStack" />
            
<param name="path">/log4j.properties</param>
            
<param name="encoding">UTF-8</param>
            
<param name="separator">_</param>
            
<param name="log4jappenderstdoutlayoutConversionPattern">
                conversionPattern
            
</param>

        
</action>
    
</package>
</struts>

  请将log4j.properties文件复制到WEB-INF/classes目录,并在该文件中加入name和price属性。

测试结果:

name:中国
price:
34
log4jappenderstdout:org.apache.log4j.ConsoleAppender
log4j_rootLogger:error
, stdout
conversionPattern:%d{ABSOLUTE} %5p %c{
1}:%L - %m%n

    由于property拦截器在defaultStack后引用,因此,在该拦截器中设置的属性值是最终结果,如果将property拦截器放在 defaultStack前面(将两个<interceptor-ref>元素掉换一下),就可以通过同名胜Action配置参数或请求参数 来干预最终究输出结果了。

posted @ 2011-11-11 17:21 AK47 阅读(350) | 评论 (0)编辑 收藏

(转贴)Struts2数据传输的背后机制:ValueStack(值栈)

     摘要: (转)Struts2数据传输的背后机制:ValueStack(值栈)原文地址 :http://blog.csdn.net/li_tengfei/article/details/6098134转载 1.     数据传输背后机制:ValueStack(值栈)   在这一切的背后,是因为有了ValueStack(值栈)!   Valu...  阅读全文

posted @ 2011-11-11 16:19 AK47 阅读(806) | 评论 (0)编辑 收藏

2011年11月9日

structs2配置UrlRewriteFilter

转载每个网页或请求都是一个url地址,一般,这个地址可能是.do,.page,.action之类的并加上'?'号、'&'号查询串等构成的一个长长的的url。很urgly。

一般的url----------------------------------------------------------较好的url
http://www.xxx.net/user/profile.do?id=20001   ====> http://www.xxx.net/user/20001
http://www.xxx.net/forum/board.do?name=java   ====> http://www.xxx.net/forum/java
http://www.xxx.net/forum/thread.do?id=29923   ====> http://www.xxx.net/thread/29923

后者明显较为直观和漂亮。

使用url rewrite可以很好的改善这个状况。网站url rewrite应用是非常广泛的,良好的url设计给用户带来的非常好的体验,同时也能吸引搜索引擎的注意。
原文地址:http://www.iteye.com/topic/53834
使用方式:
1 配置web.xml文件
样例:
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>osivFilter</filter-name>
        <filter-class>
            org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
    </filter>
    <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    <filter-mapping>
        <filter-name>osivFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--配置UrlRewriteFilter过滤器-->
    <filter>
        <filter-name>UrlRewriteFilter</filter-name>
        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>UrlRewriteFilter</filter-name>
        <url-pattern>*.html</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>
    <filter>
        <filter-name>struts-prepare</filter-name>
        <filter-class>
            org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter</filter-class>
        <init-param>
            <param-name>actionPackages</param-name>
            <param-value>com.secneo.action.*.*</param-value>
        </init-param>
    </filter>
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>

    <filter>
        <filter-name>struts-execute</filter-name>
        <filter-class>
            org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter</filter-class>
    </filter>
    <filter>
        <filter-name>struts-cleanup</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>
    <!--在structs2中使用UrlRewriteFilter过滤器-->
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>*.action</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>*.tld</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>*.tag</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>struts-prepare</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>struts-prepare</filter-name>
        <url-pattern>*.action</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>struts-prepare</filter-name>
        <url-pattern>*.tld</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>struts-execute</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>struts-execute</filter-name>
        <url-pattern>*.action</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>struts-execute</filter-name>
        <url-pattern>*.tld</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>struts-cleanup</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>struts-cleanup</filter-name>
        <url-pattern>*.action</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>struts-cleanup</filter-name>
        <url-pattern>*.tld</url-pattern>
    </filter-mapping>
    <listener>
        <listener-class>
            org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
2  在WEB-INF目录下添加urlrewrite.xml 文件,根据具体需要写规则
样例:
<?xml version="1.0" encoding="utf-8"?>
<urlrewrite>
    <rule>
        <from>^/(.*).html$</from>
        <to type="forward">/$1.action</to>
    </rule>
    <rule>
        <from>^/(.*).html?(.*)$</from>
        <to type="forward">/$1.action?$2</to>
    </rule>
</urlrewrite>

posted @ 2011-11-09 17:22 AK47 阅读(1762) | 评论 (0)编辑 收藏

structs2 filter的执行顺序

根据servlet2.3规范filter执行是按照web.xml配置的filter-mapping先后顺序进行执行。
所以自己配置的过滤器放在structs2的过滤器之前。

posted @ 2011-11-09 15:44 AK47 阅读(353) | 评论 (0)编辑 收藏

2011年11月8日

structs2拦截器

深入struct2拦截器  这篇文章很好,细致讲解了structs2和拦截器的原理。
http://zhanghong.iteye.com/blog/452465
转载在每次对你的 Action的 execute()方法请求时,系统会生成一个 ActionInvocation对象,这个对象保存了 action和你所配置的所有的拦截器以及一些状态信息。比如你的应用使用的是 defaultStack,系统将会以拦截器栈配置的顺序将每个拦截器包装成一个个 InterceptorMapping(包含拦截器名字和对应的拦截器对象 )组成一个 Iterator保存在 ActionInvocation中。在执行 ActionInvocation的 invoke()方法时会对这个 Iterator进行迭代,每次取出一个 InterceptorMapping,然后执行对应 Interceptor的 intercept(ActionInVocation inv)方法,而 intercept(ActionInInvocation inv)方法又包含当前的 ActionInInvcation对象作为参数,而在每个拦截器中又会调用 inv的 invoke()方法,这样就会进入下一个拦截器执行了,这样直到最后一个拦截器执行完,然后执行 Action的 execute()方法 (假设你没有配置访问方法,默认执行 Action的 execute()方法 )。在执行完 execute()方法取得了 result后又以相反的顺序走出拦截器栈,这时可以做些清理工作。最后系统得到了一个 result,然后根据 result的类型做进一步操作。

配置拦截器:Struts2中提供了大量的拦截器,多个拦截器可以组成一个拦截器栈,系统配置了一个默认的拦截器栈 defaultStack,具体包括那些拦截器以及顺序可以在struts-default.xml中找到。
1)
<package name="default" extends="struts-default">
   <interceptors>
       <interceptor name="timer" class=".."/>
       <interceptor name="logger" class=".."/>
   </interceptors>

   <action name="login"
      class="tutorial.Login">
        <interceptor-ref name="timer"/>
        <interceptor-ref name="logger"/>
         <result name="input">login.jsp</result>
         <result name="success"
            type="redirectAction">/secure/home</result>
   </action>
</package>

2)
<package name="default" extends="struts-default">
   <interceptors>
        <interceptor name="timer" class=".."/>
        <interceptor name="logger" class=".."/>
        <interceptor-stack name="myStack">
           <interceptor-ref name="timer"/>
           <interceptor-ref name="logger"/>
       <interceptor-ref name="defaultStack"/>    
        </interceptor-stack>
    </interceptors>

<action name="login"
     class="tutuorial.Login">
         <interceptor-ref name="myStack"/>
         <result name="input">login.jsp</result>
         <result name="success"
             type="redirectAction">/secure/home</result>
</action>
</package>

拦截器执行顺序:
<interceptor-stack name="xaStack">
  <interceptor-ref name="thisWillRunFirstInterceptor"/>
  <interceptor-ref name="thisWillRunNextInterceptor"/>
  <interceptor-ref name="followedByThisInterceptor"/>
  <interceptor-ref name="thisWillRunLastInterceptor"/>
</interceptor-stack>

执行顺序:
thisWillRunFirstInterceptor
  thisWillRunNextInterceptor
    followedByThisInterceptor
      thisWillRunLastInterceptor
        MyAction1
        MyAction2 (chain)
        MyPreResultListener
        MyResult (result)
      thisWillRunLastInterceptor
    followedByThisInterceptor
  thisWillRunNextInterceptor
thisWillRunFirstInterceptor


自定义拦截器:必须实现 com.opensymphony.xwork2.interceptor.Interceptor 也可以继承 AbstractInterceptor

拦截器要保证线程安全。因为structs2中拦截器会在请求间共享

posted @ 2011-11-08 18:35 AK47 阅读(1429) | 评论 (0)编辑 收藏

(转贴)struts2 工作原理图

     摘要: 原贴地址:http://blog.csdn.net/qjyong/article/details/1795833转贴 最近学习struts2,其实它就是webwork2.2的升级版,现附上原理图 上图来源于Struts2官方站点,是Struts 2 的整体结构。一个请求在Struts2框架中的处理大概分为以下几个步骤1 客户端初始化一个指向Servlet容器(例如Tomcat)的请求2 ...  阅读全文

posted @ 2011-11-08 15:10 AK47 阅读(1622) | 评论 (0)编辑 收藏

2011年11月1日

重新认识Java finally

关于java finally 网上有2篇文章个人认为相当不错
以下是转贴内容:

1 . JAVA finally字句的异常丢失和返回值覆盖解析
原帖地址 :
http://blog.csdn.net/sureyonder/article/details/5560538
转贴
Java虚拟机在每个try语句块和与其相关的catch子句的结尾 处都会“调用”finally子句的子例程。实际上,finally子句在方法内部的表现很象“微型子例程”。finally子句正常结束后-指的是finally子句中最后一条语句正常执行完毕,不包括抛出异常,或执行return、continue、break等情况,隶属于这个finally子句的微型子例程执行“返回”操作。程序在第一次调用微型子例程的地方继续执行后面的语句。

finally“微型子例程”不等同于方法函数的调用,finally子句都是在同一个栈内执行的,微型子例程的“返回”操作也不会涉及到方法退栈,仅仅是使程序计数器pc跳转到同一个方法的一个不同的位置继续执行。
一 异常丢失
    public static void exceptionLost()  
     {  
       try  
       {  
         try  
         {  
           throw new Exception( "exception in try" );  
         }  
         finally  
         {  
           throw new Exception( "exception in finally" );  
         }  
       }  
       catch( Exception e )  
       {  
         System.out.println( e );  
       }  
     }  

exceptionLost()的输出结果是“exception in finally”,而不是try块中抛出的异常,这是JAVA异常机制的一个瑕疵-异常丢失。

在字节码中,throw语句不是原子性操作。在较老的JDK中,exceptionLost()中try块的throw语句分解为几步操作:
1) 把Exception("exception in try")对象引用存储到一个局部变量中
  astore_2  // pop the reference to the thrown exception, store into local variable 2
2) 调用finally微型子程序
3) 把局部变量中的Exception("exception in try")对象引用push到操作数栈顶,然后抛出异常
  aload_2  // push the reference to the thrown exception from local variable 2

  athrow   // throw the exception

如果finally通过break、return、continue,或者抛出异常而退出,那么上面的第3步就不会执行。

在JDK1.6中,通过字节码我们可以看到,finally子句作为一种特殊的catch来实现的,下面是exceptionLost()方法的异常表:

Exception table:
  from   to   target  type
   0     10    10     any
 0     21    21     Class java/lang/Exception

finally可以捕获从0行到9行之间抛出的任何类型(any)的异常,并重新抛出捕获的异常,或者抛出一个自己构造的新异常,这个新异常就会覆盖try语句块中的异常。
二 返回值覆盖

    public static int getValue()  
     {  
       int value = 0;  
         
       try  
       {  
         value = 100;  
           
         return value;  
       }  
       finally  
       {  
         value = 200;  
       }  
     }  

这个方法的返回值是100还是200?结果是100。
在字节码中,return语句不是原子性操作,它会把getValue()中的return语句分解为几步操作:
1) 把value值存储到一个局部变量(这里命名为temp)中:
   iload_0   // push local variable 0 - the 100
   istore_2   //  pop an int (the 100), store into local varaible 2
2) 调用finally微型子程序
3) 把局部变量(指temp)的值push到操作数栈顶,然后返回到调用方法
     iload_2  // push local varaible 2 - the 100
   ireturn      // return int on top of the stack - the 100: return 100

由于return语句在返回之前会把返回值保存到一个临时的局部变量中,所以在finally子句内对value重新赋值不会影响返回值。

了解finally子句内在的一些知识,我们能够了解finally能够做什么和不能够做什么,这样会帮助我们正确使用finally子句。

2 . 关于 Java 中 finally 语句块的深度辨析
原帖地址 :
http://www.ibm.com/developerworks/cn/java/j-lo-finally/index.html?ca=drs-
转贴
关于 Java 虚拟机是如何编译 finally 语句块的问题,有兴趣的读者可以参考《 The JavaTM Virtual Machine Specification, Second Edition 》中 7.13 节 Compiling finally。那里详细介绍了 Java 虚拟机是如何编译 finally 语句块。实际上,Java 虚拟机会把 finally 语句块作为 subroutine(对于这个 subroutine 不知该如何翻译为好,干脆就不翻译了,免得产生歧义和误解。)直接插入到 try 语句块或者 catch 语句块的控制转移语句之前。但是,还有另外一个不可忽视的因素,那就是在执行 subroutine(也就是 finally 语句块)之前,try 或者 catch 语句块会保留其返回值到本地变量表(Local Variable Table)中。待 subroutine 执行完毕之后,再恢复保留的返回值到操作数栈中,然后通过 return 或者 throw 语句将其返回给该方法的调用者(invoker)。请注意,前文中我们曾经提到过 return、throw 和 break、continue 的区别,对于这条规则(保留返回值),只适用于 return 和 throw 语句,不适用于 break 和 continue 语句,因为它们根本就没有返回值。

posted @ 2011-11-01 16:56 AK47 阅读(816) | 评论 (0)编辑 收藏

仅列出标题  下一页
<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

统计

常用链接

留言簿

随笔分类

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜