天天看点

Struts2 Action学习

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="java">
           

学习了Struts2 中的Action,把常用到的地方记录下来。Struts2的Action在MVC的设计模式中充当了controller的角色,用于接受参数,处理部分逻辑等,相当于Servlet。其部分使用讲解如下:

一、Action的配置在struts.xml中进行Action的配置,具体可参看here。

二、Action的三种写法(Action都要在struts中配置映射)

1、自己编写普通的Java类来作为Action。

这里在类中只需要声明一个返回类型为String的public方法。

public void actionMethod(){
    System.out.println("Action ActionMethod called!");
    return success;
}
           

              要注意的是,如果方法的名字不为execute,那么要在struts.xml中的action节点配置method属性(Action默认调用的方法)才可以调用到本方法,否则struts报找不到execute错误。

<action name="first" class="com.tas.strutslearn.Action1" method="<span style="font-family: Arial, Helvetica, sans-serif;">actionMethod</span>">
    		<result>/index.jsp</result>
    	</action>
           

2、编写Java类并实现com.opensymphony.xwork2.Action接口,然后重写execute方法。

package com.tas.strutslearn;

import com.opensymphony.xwork2.Action;

public class Action2 implements Action{

	@Override
	public String execute() throws Exception {
		System.out.println("Action2 execute called!");
		return SUCCESS;
	}
}
           

3、编写Java类并继承com.opensymphony.xwork2.ActionSupport类,查看ActionSupport源码可知,本类实现了Action接口,并实现了一些其他的方法,所以在通常的使用中,会采取这种方法来编写Action。

package com.tas.strutslearn;

import com.opensymphony.xwork2.ActionSupport;

public class Action3 extends ActionSupport{
	
	@Override
	public String execute() throws Exception {
		System.out.print("Action3 execute called!!");
		return SUCCESS;
	}
}
           

三、 Action的动态方法调用

如果一个Action中有多个方法,如下:

package com.tas.strutslearn;

import com.opensymphony.xwork2.ActionSupport;

public class Action3 extends ActionSupport{
	
	@Override
	public String execute() throws Exception {
		System.out.print("Action3 execute called!!");
		return SUCCESS;
	}
	
	public String delete(){
		System.out.print("Action3 delete called!!");
		return SUCCESS;
	}
	
	public String add(){
		System.out.print("Action3 add called!!");
		return SUCCESS;
	}
}
           

那么如果指定调用哪个方法呢?以前我都是采用的在struts.xml中配置多个Action,用method区分的方法来实现:

<!-- 调用Action3的delete方法 -->
    <action name="thirddelete" class="com.tas.strutslearn.Action3" method="delete">
    	<result>/index.jsp</result>
    </action>
    <!-- 调用Action3的add方法 -->
    <action name="thirdadd" class="com.tas.strutslearn.Action3" method="add">
   	<result>/index.jsp</result>
    </action>
           

在struts2中,还有一种方法可以实现,那就是“动态方法调用”,解决了一个Action有多个请求需要配置太多的问题。使用如下:

(1)在struts中配置常量

<constant name="struts.enable.DynamicMethodInvocation" value="true" /> 
           

这个常量在struts2-core-2.3.4.jar/org.apache.struts2/default.properties中可以找到,发现其默认为true,所以这个常量一般不用配置(为false则关闭了动态方法调用)

Struts2 Action学习

(2)访问时只需要在访问路径后+“!方法名”即可,如下:

如我这里访问http://localhost:8080/002_struts2.3.4_ActionUse/third!add就可以看到方法add被调用。

注意:我们知道,早package节点配置namespace属性的时候,如果配置成“/”或“”,则在访问的路径中action前加上什么都可以访问到如http://localhost:8080/002_struts2.3.4_ActionUse/sdfsdf/dsdf//third。可是如果在这些东西中有!的话,那么struts2会认为这是动态方法调用,就会报错。所以官网上边还是不推荐使用动态方法调用这种办法。好在2.3.4版本及以后版本修复了本bug,所以,如果你使用的是2.3.4版本以前的版本,请尽量不要使用动态方法调用。

四、Action使用通配符的访问方式

通过第三部分我们发现,方法太多的时候,使用单个method属性配置麻烦,使用动态方法调用的方式又可能不安全,struts2提供了第三种方法--通配符匹配访问。通配方式不用多说,就是按照顺序出现的*和后面的按顺序的数字相匹配。

(1)struts.xml如下

<action name="third_*" class="com.tas.strutslearn.Action3" method="{1}">
    		<result>/index.jsp</result>
    	</action>
           

访问时输入http://localhost:8080/002_struts2.3.4_ActionUse/third_delete。则访问了delete方法。

(2)struts.xml如下

<action name="*_*" class="com.tas.strutslearn.{1}" method="{2}">
    		<result>/index.jsp</result>
    	</action> 
           

访问时输入http://localhost:8080/002_struts2.3.4_ActionUse/Action3_add则访问了add方法。

其他的匹配方式自己想想就可以写出来。

五、默认的Action

如果在浏览器上乱输入地址,如http://localhost:8080/002_struts2.3.4_ActionUse/sdfsfdsd/dfsdf,struts肯定会找不到“Action dfsdf的,这时,如果配置了默认的action,则不会报出错误,页面会跳转到默认的Action上边去。默认的action节点属性为<default-action-ref> 

struts.xml

<default-action-ref name="error"></default-action-ref>
    	 <action name="error">
    		<result>/error.jsp</result>
    	</action>
           

这样,当找不到action的时候就会跳转到error.jsp中去。 需要注意的是<default-action-ref> 节点必须放在error的前面(直接就作为namespace下的第一个节点吧),否则会报错。

六、Action的参数传递

这部分是struts2的重点。

(1)第一种方式是通过属性的驱动。

action写法如下:

package com.tas.strutslearn;

import java.util.Date;

import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport{

	private String username;
	
	private String password;
	
	private int age;
	
	private Date birthday;
	
	public void setUsername(String username) {
		System.out.println("UserAction setUsername called!!");
		this.username = username;
	}

	public void setPassword(String password) {
		System.out.println("UserAction setPassword called!!");
		this.password = password;
	}

	public void setAge(int age) {
		System.out.println("UserAction setAge called!!");
		this.age = age;
	}

	public void setBirthday(Date birthday) {
		System.out.println("UserAction setBirthday called!!");
		this.birthday = birthday;
	}

	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		return super.execute();
	}
	
	public String getUser(){
		System.out.println("username:"+username);
		System.out.println("password:"+password);
		System.out.println("age:"+age);
		System.out.println("birthday:"+birthday);
		return SUCCESS;
	}
}
           

表单的写法如下:

<form action="/002_struts2.3.4_ActionUse/user_getUser" method="post">
    	用户名:<input type="text" name="username"><br>
    	密 码:<input type="password" name="password"><br>
    	年 龄:<input type="text" name="age"><br>
    	生 日:<input type="text" name="birthday"><br> 
    	<input type="submit" value="提交">
    </form>
           

表单的元素的name属性一定要和Action中的属性名称一致。运行过程如下

Struts2 Action学习

可以看到其中的属性都是通过属性对应的set方法设置上去的,所以在Action中必须要写上属性的set方法。

(2)模型驱动

第一种通过属性驱动的方式,我们可以看到这种方式不利于软件项目的分层,面向对象的设计应该是尽量地将属性封装起来。

这种方式需要实现接口ModelDriven<User>,UserAction1.java(User类的创建省略):

package com.tas.strutslearn;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.tas.strutslean.entity.User;

public class UserAction1 extends ActionSupport implements ModelDriven<User>{

	private User user;
	
	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		return super.execute();
	}

	public String getUserInf(){
		System.out.println("username:"+user.getUsername());
		System.out.println("password:"+user.getPassword());
		System.out.println("age:"+user.getAge());
		System.out.println("birthday:"+user.getBirthday());
		return SUCCESS;
	}
	@Override
	public User getModel() {
		if(user==null){
			user = new User();
		}
		return user;
	}
}
           

user.jsp:

<form action="/002_struts2.3.4_ActionUse/user_getUserInf" method="post">
    	用户名:<input type="text" name="username"><br>
    	密 码:<input type="password" name="password"><br>
    	年 龄:<input type="text" name="age"><br>
    	生 日:<input type="text" name="birthday"><br> 
    	<input type="submit" value="提交">
    </form>
           

由此可以发现,User对象的创建已交由getModel方法执行。

(3)现在问题来了,属性驱动麻烦,这种ModelDriver由只能实现一个对象的数据传递,所有都还是有缺陷,所以需要第三种方法:

UserBookAction.java:

package com.tas.strutslearn;

import com.opensymphony.xwork2.ActionSupport;
import com.tas.strutslean.entity.Book;
import com.tas.strutslean.entity.User;

public class UserBookAction extends ActionSupport{
	
	private User user;
	
	private Book book;

	public User getUser() {
		System.out.println("UserBookAction getUser called!!");
		return user;
	}

	public void setUser(User user) {
		System.out.println("UserBookAction setUser called!!");
		this.user = user;
	}

	public Book getBook() {
		System.out.println("UserBookAction getBook called!!");
		return book;
	}

	public void setBook(Book book) {
		System.out.println("UserBookAction setBook called!!");
		this.book = book;
	}
	
	public String getUserBookInf(){
		System.out.println("username:"+user.getUsername());
		System.out.println("password:"+user.getPassword());
		System.out.println("age:"+user.getAge());
		System.out.println("birthday:"+user.getBirthday());
		System.out.println("author:"+book.getAuthor());
		System.out.println("bookname:"+book.getBookname());
		return SUCCESS;
	}
	
}
           

表单:

<form action="/002_struts2.3.4_ActionUse/userbook" method="post">
    	用户名:<input type="text" name="user.username"><br>
    	密 码:<input type="password" name="user.password"><br>
    	年 龄:<input type="text" name="user.age"><br>
    	生 日:<input type="text" name="user.birthday"><br> 
    	作 者:<input type="text" name="book.author"><br>
    	书 名:<input type="text" name="book.bookname"><br>
    	<input type="submit" value="提交">
    </form>
           

运行程序如下:

Struts2 Action学习

通过结果我们可以发现struts给传递对象并封装的过程:是否存在对象--》不存在new一个--》赋值一个属性--》获取对象--》赋值第二个属性--》获取对象。。。。

补充:(1)我们并没有设置程序的编码为中文,可是我们表单提交上来的数据没有乱码,这个是怎么做到的呢?这个也是struts已经设置好了的,在default.properties(目录上面有图)中可以看到有常量struts.i18n.encoding=UTF-8。

           (2)我们传递过来的参数只是String,可是到了后台却变成了int,Date等,这个也是由struts处理好了的。再也不用像Servlet里的那样,要request.getParameter()获取属性,然后再转换类型。

写完了,我现在好开心。

继续阅读