struts2入门

1.将struts2过滤器添加到web.xml中



   
        struts2
        org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
    

    
        struts2
        /*
    

2. 配置struts2的配置文件(在src目录中创建struts.xml文件)





  
    
	
    

  


3创建action(action就是一个POJO类)

     3.1、为action编写execute方法

package com.yan.struts.action;

public class HelloAction {
	public String execute(){
		System.out.println("hello struts");
		return "success";
		
	}
}

     3.2、在struts.xml文件中配置action和返回结果集






  
    
    
	
	/hello.jsp
	
    

  


默认执行execute方法,但有多个操作显然不够,所以可以进行指定执行哪个方法






  
    
    
	
	/WEB-INF/user/addInput.jsp
	
		
	/WEB-INF/user/add.jsp
	
		
	/WEB-INF/user/list.jsp
	
    

  




package com.yan.struts.action;

public class UserAction {
	public String addInput(){
		System.out.println("addInput");
		return "success";
		
	}
	public String add(){
		System.out.println("add");
		return "success";
		
	}
	public String list(){
		System.out.println("list");
		return "success";
		
	}
}

上述配置使得可以在一个action类中写多个方法,不用受execute影响建多个action类,但在配置中依旧需要配置多个action

package com.yan.struts.action;

public class UserAction {
	public String addInput(){
		System.out.println("addInput");
		return "success";
		
	}
	public String add(){
		System.out.println("add");
		return "success";
		
	}
	public String list(){
		System.out.println("list");
		return "success";
		
	}
}







  
    
    
	
	/WEB-INF/User/add.jsp
	/WEB-INF/User/addInput.jsp
	/WEB-INF/User/list.jsp
	
    


用上述配置就可以在调用时确定调用的方法,以"(actionname)!(要调用的方法名)"为url,如要调用UserAction中的add方法,可以使用User!add,还有一种通过(actionname)?method:(要调用的方法名)访问。
这些方法依旧要做大量的返回值配置,还有一种通配符配置
package com.yan.struts.action;

public class UserAction {
	public String addInput(){
		System.out.println("addInput");
		return "success";
		
	}
	public String add(){
		System.out.println("add");
		return "success";
		
	}
	public String list(){
		System.out.println("list");
		return "success";
		
	}
}






  
    
    
	
	/WEB-INF/{1}/{2}.jsp
	
    

 

url输入User_add时,{1}为User,{2}为add,即调用UserAction中的add方法,页面跳转到User文件夹下的add.jsp目录。这样的好处显而易见,如果还有其他的Action类,以actionname_方法名也适用,自动调用,省去一大批配置,当然文件夹名和jsp名要按照一定约束命名。
----------------------------------------------------------------------------------------------
传值的方式(指的是action传给视图的方式,而form给action只要action有set get方法,直接传,action可以直接获取):
方式一:通过属性。
package com.yan.struts.action;

public class UserAction {
	private String name;
	private int age;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String addInput(){
		System.out.println("addInput");
		return "success";
		
	}
	public String add(){
		System.out.println("add");
		return "success";
		
	}
	public String list(){
		this.setName("张三");
		this.setAge(20);
		System.out.println("list");
		return "success";
		
	}
}

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




Insert title here


User list

${name}----${age }

或者struts有自己的标签库
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>




Insert title here


User list

----

方式二:通过actionContext传值,其实就是存进一个Map
public String list(){
	
		ActionContext.getContext().put("aaa","张三");
	        ActionContext.getContext().put("bbb", "123");
                System.out.println("list");
		return "success";
		
	}
获取
---- 
访问actionContext中的数据都需要加#,不过如果存的是字符串,struts2.3以后可以不用#号
方式三:通过servlet的API传值
public String list(){
	
	        ServletActionContext.getRequest().setAttribute("hello", "world");
		System.out.println("list");
		return "success";
		
	}
获取
获取值的方式又不一样,如果是#hello是获取不到,什么原因?我们需要学一下ognl和ValueStack,要理解根本
--------------------------------------------------------------------------------------------------
package com.yan.struts.test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Test;

import com.yan.struts.model.Department;
import com.yan.struts.model.Role;
import com.yan.struts.model.User;

import ognl.Ognl;
import ognl.OgnlException;

public class TestOgnl {

	@Test
	public void test01() {
		 
		try {
			User u=new User(1,"ts","唐三");
			//第二个参数为root,意思是输出u的id值
			System.out.println(Ognl.getValue("id", u));
			Department de=new Department("财务部");
			u.setDe(de);
			System.out.println(Ognl.getValue("de.name", u));
		} catch (OgnlException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@Test
	public void test02() {
		
		try {
			Map ctx=new HashMap();
			User u=new User(1,"ts","唐三"); 
			
			Department de=new Department("财务部");
			Role r=new Role(1,"管理员");
			ctx.put("user", u);
			ctx.put("role", r);
		        u.setDe(de);
		        //在根root即u中找username
			System.out.println(Ognl.getValue("username",ctx, u));
			//加#号在map即ctx中找所存的user的username
			System.out.println(Ognl.getValue("#user.username",ctx, u));
			//目前root是ctx所以也可以取到
			System.out.println(Ognl.getValue("role.name", ctx,ctx));
			//Ognl其实就是一个大的Context(Map),根的key就是root,值为u
			System.out.println(Ognl.getValue("#root.username",ctx,u));
			
		} catch (OgnlException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@Test
	public void test03() {
		
		try {
			Listusers=new ArrayList();
			users.add(new User(1,"张三","zs"));
			users.add(new User(2,"王五","ww"));
			users.add(new User(3,"赵六","zl"));
			//root为list要用#root[index]方式访问
		    System.out.println(Ognl.getValue("#root[0].username",users));
			
		} catch (OgnlException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
       @Test
       public void test04() {
  
                try {
                        User u=new User();
                        //可以调用方法
                        System.out.println(Ognl.getValue("add(1,2)", u));
                        System.out.println(Ognl.getValue("hello('world')", u));
                        //在test03还可以  
                        System.out.println(Ognl.getValue("get(1).username",users));
                } catch (OgnlException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
         }
}


package com.yan.struts.model;

public class User {
	private int id;
	public Department de;
	private String username;
	private String nickname;
	
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getNickname() {
		return nickname;
	}
	public void setNickname(String nickname) {
		this.nickname = nickname;
	}
	public Department getDe() {
		return de;
	}
	public void setDe(Department de) {
		this.de = de;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}

	public User(int id, String username, String nickname) {
		super();
		this.id = id;
		this.username = username;
		this.nickname = nickname;
	}
	public User() {
                super();
        }
        public int add(int a,int b){
                return a+b;
        }
        public String hello(String para){
                return "hello"+para;
        }
 

	
}




package com.yan.struts.model;

public class Department {
 private String name;

public String getName() {
	return name;
}

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

public Department(String name) {
	super();
	this.name = name;
}
 
}

package com.yan.struts.model;

public class Role {
   private int id;
   private String name;
public int getId() {
	return id;
}
public void setId(int id) {
	this.id = id;
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public Role(int id, String name) {
	super();
	this.id = id;
	this.name = name;
}
   
}

对于struts,所有值都存在ValueStack中,ValueStack包括ActionContext(其实是个Map)和CompoundRoot(使用list的栈结构),调用一个action时将它进栈,当使用compoundRoot时使用#root[0]表示从第一个元素(栈顶)取数据(不加如username也是取第一个元素的username),取不到就取下一个元素的username,以此类推。
现在回过头可以理解获取方式一传值的时候直接value="username"就可以,因为他是从root中取值(TestOgnl里的test01),而获取方式二所传的值要用#aaa,因为是存在actionContext(Map)里的(test02),同理方式三,actionContext里存request。
可以往compoundRoot添加一个元素自己做做测试
UserAction中的list方法
        this.setName("八戒");
        this.setAge(123);
        User u=new User(10,"孙悟空","swn");
	ActionContext.getContext().getValueStack().push(u);
此时栈中存了UserAction对象和对象u,可以自己测试#root[0].XXX会获取哪个元素
可以在页面查看compoundRoot和actionContext,里面的都可以用对应的方法取出

----------------------------------标签--------------------------------------------------------------------
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>




Insert title here


User list

成年人 未成年 -------

	public String list(){
		Listusers=new ArrayList();
		users.add(new User(1,"张三","zs"));
		users.add(new User(2,"王五","ww"));
		users.add(new User(3,"赵六","zl"));
		ActionContext.getContext().put("users", users);

		return "success";
		
	}

设置status是在ActionContext中放一份
-------------------------------------------------------------------------------------------------------------
当一个类有太多属性,比如User有username还有邮箱地址等许多属性,在UserAction中一个一个写出来要写太多东西,很冗余,而且set和get方法就更多了,因此我们可以将User一整个作为属性。如MessageAction中:
package com.yan.struts.action;

import com.yan.struts.model.Message;

public class MessageAction {
	private Message msg;

	public Message getMsg() {
		return msg;
	}

	public void setMsg(Message msg) {
		this.msg = msg;
	}
	public String addInput(){
		
		return "success";
		
	}
	public String add(){
		
		return "success";
		
	}
}


package com.yan.struts.model;

public class Message {
	private int id;
	private String title;
	private String content;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	
}

这样就简化很多,表单提交时自动映射到对应的值,就相当于form传值给action
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




Insert title here


Message addInput

id:
title:
content:

提交后的url可以看出传值自动映射了
http://localhost:8080/Struts01/Message_add.action?msg.id=3&msg.title=fff&msg.content=eee
可以看到表单的name值都要加上msg.,有点繁琐,我们可以有更好的方法,让MessageAction实现ModelDriver接口
package com.yan.struts.action;

import com.opensymphony.xwork2.ModelDriven;
import com.yan.struts.model.Message;

public class MessageAction implements ModelDriven{
	private Message msg;

	public Message getMsg() {
		return msg;
	}

	public void setMsg(Message msg) {
		this.msg = msg;
	}
	public String addInput(){
		
		return "success";
		
	}
	public String add(){
		
		return "success";
		
	}

	@Override
	public Message getModel() {
		if(msg==null)msg=new Message();
		return msg;
	}
}

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




Insert title here


Message addInput

id:
title:
content:

原理:实现ModelDriver接口重写getModel方法后,会将对应的Model对象push到root的栈中
struts2入门_第1张图片
此时name为msg.id(MessageAction中)或id(Message)都可以

--------------------------------------------------------类型转化器--------------------------------------------------
如果MessageAction有一个point属性,我们想在文本框输入x,y形式设置point的值是做不到的,我们需要利用转换器
package com.yan.struts.action;

import java.util.Date;

import com.opensymphony.xwork2.ModelDriven;
import com.yan.struts.model.Message;
import com.yan.struts.model.Point;

public class MessageAction implements ModelDriven{
	private Message msg;
	private Point point;
	
	public Point getPoint() {
		return point;
	}

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

	public Message getMsg() {
		return msg;
	}

	public void setMsg(Message msg) {
		this.msg = msg;
	}
	public String addInput(){
		
		return "success";
		
	}
	public String add(){
		
		return "success";
		
	}

	@Override
	public Message getModel() {
		if(msg==null)msg=new Message();
		return msg;
	}
}

package com.yan.struts.model;

public class Point {
 private String x;
 private String y;
public String getX() {
	return x;
}
public void setX(String x) {
	this.x = x;
}
public String getY() {
	return y;
}
public void setY(String y) {
	this.y = y;
}
 
}

package com.yan.struts.converter;

import java.util.Map;

import org.apache.struts2.util.StrutsTypeConverter;

import com.yan.struts.model.Point;

public class PointConverter extends StrutsTypeConverter {

	@Override
	public Object convertFromString(Map context, String[] values, Class toClass) {
		Point p=null;
		if(values.length<=1){
			String str=values[0];
			String []codes=str.split(",");
			p=new Point();
			p.setX(codes[0]);
			p.setY(codes[1]);
		}
		return p;
	}

	@Override
	public String convertToString(Map context, Object o) {
		Point p=(Point)o;
		return p.getX()+","+p.getY();
	}

}

可以设置全局转化器,创建xwork-conversion.properties文件
com.yan.struts.model.Point=com.yan.struts.converter.PointConverter
可以设置局部转化器,创建MessageAction-conversion.properties文件
point=com.yan.struts.converter.PointConverter

获取值${point}无法获取,要用
---------------------------------------------文件上传----------------------------------------------------------
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




文件上传



package com.yan.struts.action;

import java.io.File;
import java.io.IOException;
import java.util.Date;

import org.apache.commons.io.FileUtils;

import com.opensymphony.xwork2.ModelDriven;
import com.yan.struts.model.Message;
import com.yan.struts.model.Point;

public class MessageAction implements ModelDriven{
	private Message msg;
	private Point point;
	private Date endTime;
	private File photo;
	private String photoFileName;
	private String photoContentType;
	
	public String getPhotoFileName() {
		return photoFileName;
	}

	public void setPhotoFileName(String photoFileName) {
		this.photoFileName = photoFileName;
	}

	public String getPhotoContentType() {
		return photoContentType;
	}

	public void setPhotoContentType(String photoContentType) {
		this.photoContentType = photoContentType;
	}

	public File getPhoto() {
		return photo;
	}

	public void setPhoto(File photo) {
		this.photo = photo;
	}

	public Date getEndTime() {
		return endTime;
	}

	public void setEndTime(Date endTime) {
		this.endTime = endTime;
	}

	public Point getPoint() {
		return point;
	}

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

	public Message getMsg() {
		return msg;
	}

	public void setMsg(Message msg) {
		this.msg = msg;
	}
	public String addInput(){
		
		return "success";
		
	}
	public String add(){
		
		return "success";
		
	}

	@Override
	public Message getModel() {
		if(msg==null)msg=new Message();
		return msg;
	}
	public String fileInput(){
		return "success";
	}
	public String file(){
		
		try {
			System.out.println(photoFileName+"..."+photoContentType);
			FileUtils.copyFile(photo, new File("d:/"+photoFileName));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "success";
	}
}
文件上传的大小可以通过设置类似
其他属性也可以设置
----------------------------------------拦截器-----------------------------------------------------
首先创建类继承AbstractInterceptor
package com.yan.struts.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class HelloInterceptor extends AbstractInterceptor {

	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		System.out.println("hello interception");
		return invocation.invoke();
		
	}

}






  
    
    
    
    
    
	
	
	
	/WEB-INF/{1}/{2}.jsp
	
	
    

 

上述的配置有问题,因为继承了struts-default。默认使用了defaultStack,而这个栈包含了许多拦截器。但在action添加了自己的拦截器就不在默认使用,少了那些拦截器会让程序出现问题。我们可以进行如下修改:
手动添加defaultStack





  
    
    
    
    
   
    
	
	
	
	
	/WEB-INF/{1}/{2}.jsp
	
	
    

 

或者自己创建一个栈包含defaultStack,然后在action中引入自定义栈





  
    
    
    
    
    
    
    
    
    
	
	
	
	
	/WEB-INF/{1}/{2}.jsp
	
	
    

 



你可能感兴趣的:(struts2.0)