struts2入门

223 阅读8分钟

struts2的hello world

1、导包(自行导包)

2、配置web.xml文件

    struts2基于拦截器,配置的第一步是在WEB-INF/web.xml中配置struts2拦截器。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>struts2</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <!-- 配置struts2核心过滤器 -->
  <filter>
  	<filter-name>struts2</filter-name>
  	<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>
  
  <filter-mapping>
  	<filter-name>struts2</filter-name>
	<url-pattern>/*</url-pattern>  	
  </filter-mapping>
 
</web-app>

3、配置struts.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
    "http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
    <!-- 
    package: 包,struts2 使用 package 来组织模块.
    name属性:必须,用于其它的包引用当前包.
    extends:当前包继承哪个包,即可以继承其中的所有的配置,通常情况下继承 struts-default
	        struts-default 这个包在 struts-default.xml 文件中定义
    namespace:可选, 如果它没有给出,则以 / 为默认值. 
		    若 namespace 有一个非默认值,则要想调用这个包里的Action,
		    就必须把这个属性所定义的命名空间添加到有关的 URI 字符串里 
		    http://localhost:8080/contextPath/namespace/actionName.action 
    -->
    <package name="default" namespace="/" extends="struts-default">
        <!--
        action:一个 struts2 的请求就是一个 action 
    	name:对应一个 struts2 的请求的名字(或对一个 servletPath, 但去除 / 和扩展名)
    	class:当前 action 所属的全类名,默认值为: com.opensymphony.xwork2.ActionSupport
    	method:当前 action 对应的方法名,默认值为: execute
    	--> 
	<action name="hello" class="com.bjlemon.action.HelloAction" method="execute">
    	<!--
    	result: 结果,表示 action 方法执行后可能返回的一个结果。
    	        一个 action 节点可能会有多个 result 子节点.
    			多个 result 子节点使用 name 来区分
    			name:标识一个 result 和 action 方法的返回值对应,默认值为 success
    			type: 表示结果的类型. 默认值为 dispatcher(转发到结果.)
    	-->
		<result name="success" type="dispatcher">/hello.jsp</result>
		
		<action name="index">
			<result>/index.jsp</result>
		</action>
	</action>
    </package>
    <!-- 就是引入其他的struts2配置文件 -->
    <!-- <include file=""></include> -->
</struts>

4、写一个HelloAction类

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

5、编写一个hello.jsp页面和index.jsp页面

hello.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>struts2</title>
    </head>
        <body>
        hello world
        </body>
</html>

index.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>struts2</title>
    </head>
        <body>
        hello struts
        </body>
</html>

6、测试

    配置好后,就可以通过浏览器访问(根路径取决于项目配置) 
    http://127.0.0.1/strut2/hello.action
    如果访问成功,jsp页面也会显示hello struts
    http://127.0.0.1/strut2/hello.action 
    如果访问成功,控制台后打印 hello world,jsp页面也会显示hello world

7、补充(注解配置如下)

// 使用注解前必须导入 struts2-convention-plugin 包
@ParentPackage("struts-default")
public class HelloAction extends ActionSupport{

    @Action(value="hello",results= {
            @Result(name="success",location="/hello.jsp")
    })
    public String execute() {
        System.out.println("hello world");
        return "success";
    }
    
}

struts2常量配置

<!-- 处理乱码 -->
<constant name="struts.i18n.encoding" value="UTF-8"></constant>
<!-- 配置访问后缀名 -->
<constant name="struts.action.extension" value="action,,"></constant>
<!-- 是否开启开发模式(热加载) -->
<constant name="struts.devMode" value="false"></constant>
<!-- 调用动态方法 -->  
  <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>

动态方法调用

HelloAction

public class HelloAction extends ActionSupport{
    public String execute() {
        System.out.println("hello world");
        return "success";
    }
    
    public String execute1() {
        System.out.println("hello world1");
        return "success";
    }
    
    public String execute2() {
        System.out.println("hello world2");
        return "success";
    }
}
<!-- 如果请求的时候找不到Action,就会执行index -->
<default-action-ref name="showStudent"></default-action-ref>
<!-- 动态方法允许调用的方法名 -->
<global-allowed-methods>execute1,execute2,execute3</global-allowed-methods>
<!-- 动态方法调用(第一种感叹号不常用),访问hello!方法名 -->
<action name="hello" class="com.bjlemon.action.HelloAction">
	<result name="success">/hello.jsp</result>
</action>

<!-- 动态方法调用(第二种通配符常用),访问hello_方法名 -->
<action name="hello_*" class="com.bjlemon.action.HelloAction" method="{1}">
	<result name="success">/hello.jsp</result>
</action>

Action的创建方式

//第一种方式
public class HelloAction{}

//第二种方式
public class Test implements Action{
    @Override
    public String execute() throws Exception {
        // TODO Auto-generated method stub
        return null;
    }
}

//第三种方式
public class HelloAction extends ActionSupport{}

Action中result处理方式

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
    "http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="default" namespace="/" extends="struts-default">
<!-- 第一种:请求转发(type="dispatcher")默认方式 -->
<action name="hello1" class="com.bjlemon.action.Action1" method="hello1">
	<result name="success1" type="dispatcher">/hello.jsp</result>
</action>

<!-- 第二种:请求重定向(type="redirect") -->
<action name="hello2" class="com.bjlemon.action.Action1" method="hello1">
	<result name="success1" type="redirect">/hello.jsp</result>
</action>

<!-- 第三种:请求转发到Action(type="chain") -->
<action name="hello3" class="com.bjlemon.action.Action1" method="hello1">
	<result name="success1" type="chain">
		<!-- 跳转的action的名字 -->
		<param name="actionName">hello1</param>
		<!-- 跳转的action的命名空间 -->
		<param name="namespace">/</param>
	</result>
</action>

<!-- 第四种:请求重定向到Action(type="redirectAction") -->
<action name="hello4" class="com.bjlemon.action.Action1" method="hello1">
	<result name="success1" type="redirectAction">
		<!-- 跳转的action的名字 -->
		<param name="actionName">hello1</param>
		<!-- 跳转的action的命名空间 -->
		<param name="namespace">/</param>
	</result>
</action>
</package>
</struts>

Action获取servlet api

//获得原生的servlet作用域对象  方式一
public class Action1 extends ActionSupport{
    public String hello1() {
        HttpServletRequest request=ServletActionContext.getRequest();
        request.setAttribute("key", "value");
        HttpSession session=request.getSession();
        HttpServletResponse response=ServletActionContext.getResponse();
        ServletContext servletContext=ServletActionContext.getServletContext();
        return "success1";
    }
}

//获得原生的servlet作用域对象  方式二
public class Action1 extends ActionSupport implements ServletRequestAware,ServletResponseAware,ServletContextAware{
    private HttpServletRequest request;
    private HttpServletResponse response;
    private ServletContext servletContext;
    @Override
    public void setServletRequest(HttpServletRequest request) {
        this.request=request;
        HttpSession session=request.getSession();
    }
    @Override
    public void setServletResponse(HttpServletResponse response) {
        this.response=response;
    }
    @Override
    public void setServletContext(ServletContext servletContext) {
        this.servletContext=servletContext;
        
    }
}

//获得原生的ActionContext作用域对象(常用)  方式一
public class Action1 extends ActionSupport{
    public String hello2() {
        Map<String, Object> request=(Map<String, Object>)ActionContext.getContext().get("request");
        ActionContext context=ActionContext.getContext();
        context.put("key", "value");
        Map<String, Object> session=ActionContext.getContext().getSession();
        session.put("key", "value");
        Map<String, Object> application=ActionContext.getContext().getApplication();
        return "success1";
    }
}

//获得原生的ActionContext作用域对象(常用)  方式二
public class Action1 extends ActionSupport implements RequestAware, SessionAware, ApplicationAware {
    private Map<String, Object> request;
    private Map<String, Object> session;
    private Map<String, Object> application;
    @Override
    public void setRequest(Map<String, Object> request) {
        this.request = request;
    }
    @Override
    public void setSession(Map<String, Object> session) {
        this.session = session;
    }
    @Override
    public void setApplication(Map<String, Object> application) {
        this.application = application;
    }
}

struts2接收前台传过来的参数的方式

第一种方式:属性加载驱动

index.jsp

<form action="${pageContext.request.contextPath}/hello1" method="post">
	<input type="text" name="name">
	<input type="text" name="age">
	<input type="text" name="date">
	<input type="submit" value="提交">
</form>
public class Action1{
    private String name;
    private Integer age;
    private Date date;
    //...省略getter/setter方法
    public String hello1() {
        System.out.println(name+"-"+age+"-"+date);
        return "success1";
    } 
}

第二种方式:对象加载驱动

index.jsp

<form action="${pageContext.request.contextPath}/hello1" method="post">
	<input type="text" name="student.name">
	<input type="text" name="student.age">
	<input type="text" name="student.date">
	<input type="submit" value="提交">
</form>

Student.java

public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private Date date;
    //...省略getter/setter方法
}
public class Action1{
    private Student student;
    //...省略getter/setter方法
    public String hello1() {
        System.out.println(student);
        return "success1";
    } 
}

第三种方式:ModelDriven模型驱动

index.jsp

<form action="${pageContext.request.contextPath}/hello1" method="post">
	<input type="text" name="name">
	<input type="text" name="age">
	<input type="text" name="date">
	<input type="submit" value="提交">
</form>
public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private Date date;
    //...省略getter/setter方法
}
public class Action1 implements ModelDriven<Student>{
    private Student student=new Student();
    public String hello1() {
        System.out.println(student);
        return "success1";
    }
    @Override
    public Student getModel() {
        return student;
    } 
}

接收list集合

<form action="${pageContext.request.contextPath}/hello1" method="post">
	<input type="text" name="list">
	<input type="text" name="list">
	<input type="text" name="list">
	<input type="submit" value="提交">
</form>
public class Action1{
    private List<String> list;
    //...省略getter/setter方法
    public String hello1() {
        System.out.println(list);
        return "success1";
    }

}

接收map集合

<form action="${pageContext.request.contextPath}/hello1" method="post">
	<input type="text" name="map['KEY0']">
	<input type="text" name="map['KEY1']">
	<input type="text" name="map['KEY2']">
	<input type="submit" value="提交">
</form>
public class Action1{
    private Map<String,String> map;
    //...省略getter/setter方法
    public String hello1() {
        System.out.println(map);
        return "success1";
    }
}

值栈(ValueStack)

  • 栈:先进后出
  • 队列:先进先出

struts拦截器

StudentAction.java

public class StudentAction {
    public String getAdd() {
        System.out.println("add");
        return "success";
    }
    public String getUpdate() {
        System.out.println("update");
        return "success";
    }
    public String getDel() {
        System.out.println("del");
        return "success";
    }
    public String getSelect() {
        System.out.println("select");
        return "success";
    }
}

MyInterceptor3.java

//自定义拦截器
public class MyInterceptor3 extends MethodFilterInterceptor{
    private static final long serialVersionUID = 1L;
    @Override
    protected String doIntercept(ActionInvocation invocation) throws Exception {
        //前处理
        System.out.println("before");
        invocation.invoke();
        //后处理
        System.out.println("after");
        //返回结果集,不执行后面的拦截器,直接给result处理结果集,跳转页面
        return null;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
    "http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>

	<package name="default" namespace="/" extends="struts-default">
		<!-- 1.配置拦截器 -->
		<interceptors>
			<interceptor name="myInterceptor3" class="com.bjlemon.interceptor.MyInterceptor3"></interceptor>
			<!-- 2.配置拦截器栈 -->
			<interceptor-stack name="myInterceptor">
				<!-- 引入自定义的拦截器 -->
				<interceptor-ref name="myInterceptor3">
					<!-- excludeMethods,includeMethods只能出现一个 -->
					<!-- 指定不进行拦截的方法 -->
					<!-- <param name="excludeMethods">getAdd,getUpdate</param> -->
					<!-- 指定进行拦截的方法 -->
					<param name="includeMethods">getDel,getSelect</param>
				</interceptor-ref>
				<!-- 引入struts2的默认拦截器栈 -->
				<interceptor-ref name="defaultStack"></interceptor-ref>
			</interceptor-stack>
		</interceptors>
		<!-- 配置默认的拦截器栈 -->
		<default-interceptor-ref name="myInterceptor"></default-interceptor-ref>
		<global-allowed-methods>getAdd,getUpdate,getDel,getSelect</global-allowed-methods>
	</package>
</struts>

struts2的执行流程

  • 用户请求前端控制器(StrutspreapredAndExecuteFilter),它是一个 Filter,拦截用户的请求,根据用户请求的url调用Action
  • 前端控制器(StrutsPrepareAndExecuteFilter)判定该请求是否是一个Struts2 请求(ActionMapper)
  • 若该请求是一个Struts2请求,则前端控制器StrutsPrepareAndExecuteFilter 把请求的处理交给ActionProxy
  • ActionProxy创建一个ActionInvocation的实例,并进行初始化
  • ActionInvocation实例在调用 Action 的过程前后,涉及到相关拦截 器(Intercepter)的调用。
  • Action 执行完毕,ActionInvocation 负责根据struts.xml中的配置 找到对应的result,渲染结果。
  • 执行各个拦截器 invocation.invoke() 之后的代码
  • 把结果发送到客户端