目录

一、Struts框架中如何使用原生Servlet的API

方法一、使用ActionContext类(完全解耦合的方式)(不好用,了解)

demo1.jsp

demo1Action.java   ★

struts.xml

suc.jsp

方法二、使用ServletActionContext类(原生Servlet的API的方式)(好用,掌握)★

demo1.jsp里加上

demo2Action.java

小插曲:页面的跳转result的配置总结

1.全局结果页面配置

2.跳转类型设置

dispatcher

redirect

redirectAction

二、struts2专门的数据封装  ★

1.属性驱动方式(封装到Action内定义的属性里)★

demo2.jsp

struts.xml

Regist1Action.java

2.属性驱动方式(封装到action的类成员变量里 前端要写OGNL麻烦 )(了解即可)

demo2.jsp  注意name写法

struts.xml

User.java

Regist2Action.java

3.模型驱动(前端name值不用写OGNL,也可封装到javaBean类对象中)★

前端demo2.jsp 写法没啥特殊之处了

struts.xml

Regist3Action.java

三、拦截器


struts框架环境如何搭建上篇已经介绍  今日资料下载: 直接下载struts2_2.zip       网盘备份下载

 

一、Struts框架中如何使用原生Servlet的API

案例需求:使用Struts2作为WEB层完成客户的新增功能

提供JSP的表单页面的数据,在Action中使用Servlet的API接收到,然后保存到三个域对象中,最后再显示到JSP的页面上。
        * 提供JSP注册的页面
            <h3>注册页面</h3>
            <form action="${ pageContext.request.contextPath }/xxx.action" method="post">
                姓名:<input type="text" name="username" /><br/>
                密码:<input type="password" name="password" /><br/>
                <input type="submit" value="注册" />
            </form>
 

方法一、使用ActionContext类(完全解耦合的方式)(不好用,了解)

Struts2框架中提供了一个类,ActionContext类,该类中提供一些方法,通过方法获取Servlet的API
一些常用的方法如下:
  static ActionContext getContext()                  -- 获取ActionContext对象实例(这么获取自己,不需要new
  Map<String,Object> getParameters()            -- 获取请求参数,相当于request.getParameterMap();
  Map<String,Object> getSession()                  -- 获取的代表session域的Map集合(原生的session被放到Map集合中了)
  Map<String,Object> getApplication()             -- 获取代表application域的Map集合
  void put(String key,Object value)                    -- 注意:向request域中存入值 (没有getRequest,用起来反而不习惯了

demo1.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>demo1</title>
  </head>
  <body>
    	<h1>使用ActionContext类使用原生Servlet的API(方法一,完全解耦合)</h1>
    	<h3>注册页面</h3>
		<form action="${ pageContext.request.contextPath }/demo1Action.action" method="post">
        	姓名:<input type="text" name="username" /><br/>
        	密码:<input type="password" name="password" /><br/>
                <input type="submit" value="注册" />
		</form>
  </body>
</html>

demo1Action.java   ★

package cn.ahpu.action;

import java.util.Arrays;
import java.util.Map;
import java.util.Set;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class demo1Action extends ActionSupport {
	@Override
	public String execute() throws Exception {
		//完全解耦合方式获取servlet的api进而前台数据
		ActionContext context = ActionContext.getContext();//先获取ActionContext
		//getParameters会封装所有的请求参数
		Map<String, Object> map = context.getParameters();//然后就可以通过context调用servlet的api获取数据了
		//拿到map所有key,再通过key遍历map
		Set<String> keys = map.keySet();
		for (String key : keys) {
			//通过key获取值
			String[] vals = (String[]) map.get(key);
			System.out.println(key+" : "+Arrays.toString(vals));
		}
		
		//其他api使用演示
		context.getSession().put("msg", "Session成功!");
		context.getApplication().put("msg", "Application成功!");
		context.put("msg", "Resquest成功!");//直接put中间不写get默认getResquest了,因为太常用了,因此这么简单点设计
		
		return SUCCESS;
	}
}

struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
	<!DOCTYPE struts PUBLIC
		"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
		"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
	<package name="struts02" namespace="/" extends="struts-default">
		<action name="demo1Action" class="cn.ahpu.action.demo1Action">
			<result name="success">/demo1/suc.jsp</result>
		</action>
		<!-- 上两行决定了请求路径为  项目名/demo1Action.action  此处访问默认方法execute-->
	</package>
</struts>

suc.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>sucess el表达式</title>
  </head>
  <body>
    	<h3>默认最小域(request)的msg:${msg }</h3>
    	<h3>requestScope:${requestScope.msg }</h3>
    	<h3>sessionScope:${sessionScope.msg }</h3>
    	<h3>applicationScope:${applicationScope.msg }</h3>
  </body>
</html>

测试:

 

 

 

方法二、使用ServletActionContext类(原生Servlet的API的方式)(好用,掌握)

jsp+servlet基础学得比较熟的,此方法比较简单直接,推荐
Struts2框架提供了一个类,ServletActionContext,该类中提供了一些静态的方法
具体的方法如下
    getPageContext()
    getRequest()     
    getResponse()
    getServletContext()
可以直接获取未封装的原生的request/response等api,获取后用起来很顺手,用来接收或传递简单几个参数时很方便

demo1.jsp里加上

<h1>使用ServletActionContext类使用原生Servlet的API(方法二,比较简单顺手,常用)</h1>
    	<h3>注册页面</h3>
		<form action="${ pageContext.request.contextPath }/demo2Action.action" method="post">
        	姓名:<input type="text" name="username" /><br/>
        	密码:<input type="password" name="password" /><br/>
                <input type="submit" value="注册" />
		</form>

demo2Action.java

package cn.ahpu.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class demo2Action extends ActionSupport {
	private static final long serialVersionUID = 1L;

	@Override
	public String execute() throws Exception {
		//似乎不封装数据 也默认会帮你放到session中 只要传递了
		HttpServletRequest request = ServletActionContext.getRequest();
		String name = request.getParameter("username");
		String pwd = request.getParameter("password");
		System.out.println("name:"+name+"\npwd:"+pwd);
		
		request.setAttribute("msg", "request值");
		request.getSession().setAttribute("msg", "session值");
		request.getServletContext().setAttribute("msg", "application值");//可还记得getServletContext()就是application
		//ServletActionContext.getServletContext().setAttribute("msg", "application值");//可以直接拿
		
		//找不到的api就写ServletActionContext. 根据提示肯定能找到
		HttpServletResponse response = ServletActionContext.getResponse();
		//response.getWriter().print("<br>response.getWriter打印值<br>");
		//一调用response.getWriter前端就乱码,所以不要这么用了 好不容易框架自动处理了乱码,可别给破坏了
		
		return SUCCESS;
	}
}

 

小插曲:页面的跳转result的配置总结

1. 结果页面存在两种方式
    * 全局结果页面
        > 条件:如果<package>包中的一些action都返回success,并且返回的页面都是同一个JSP页面,这样就可以配置全局的结果页面。
        > 全局结果页面针对的当前的包中的所有的Action,但是如果局部还有结果页面,会优先局部的。使用的标签是
            <global-results>
                <result>/demo3/suc.jsp</result>
            </global-results> 
    
    * 局部结果页面
        <action ..>
            <result>/demo3/suc.jsp</result>
        </action ..>

2. 结果页面的类型
    * 结果页面使用<result>标签进行配置,包含两个属性
        > name    -- 逻辑视图的名称  就是匹配返回值
        > type    -- 跳转的类型,值一些,需要掌握一些常用的类型。常见的结果类型去struts-default.xml中查找。
            * dispatcher        -- 转发.默认值.Action--->JSP
            * redirect            -- 重定向.Action--->JSP
            * chain                -- 多个action之间跳转.Action---转发---Action
            * redirectAction    -- 多个action之间跳转.Action---重定向---Action 
            * stream            -- 文件下载时候使用的
 

1.全局结果页面配置

删掉上例子中两个action中同样的result配置,外面加一个global-results

<global-results>
            <result name="success">/demo1/suc.jsp</result>
</global-results>

<?xml version="1.0" encoding="UTF-8" ?>
	<!DOCTYPE struts PUBLIC
		"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
		"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
	<package name="struts02" namespace="/" extends="struts-default">
		
		<!-- 下面两个action的跳转一模一样,删除,在外面配置一个全局的即可 -->
		<global-results>
			<result name="success">/demo1/suc.jsp</result>
		</global-results>
	
		<action name="demo1Action" class="cn.ahpu.action.demo1Action">
			<!-- <result name="success">/demo1/suc.jsp</result> -->
		</action>
		
		<action name="demo2Action" class="cn.ahpu.action.demo2Action">
			<!-- <result name="success">/demo1/suc.jsp</result> -->
		</action>
		
	</package>
</struts>

依然正常运行,效果一样!

 

2.跳转类型设置

dispatcher

默认值  请求转发  action->jsp

修改(就是加个type="dispatcher")上例后 正常执行

 

redirect

重定向  action->jsp

改成转发,再次运行,request域中的值就传递不了了

 

redirectAction

重定向到Action  Action->Action   Action之间跳转路径不能写太详细  写匹配好的Action的name即可

演示重Demo3Action_save方法跳到Demo3Action_update

Demo3Action.java

package cn.ahpu.action;

import com.opensymphony.xwork2.ActionSupport;

public class Demo3Action extends ActionSupport {
	
	public String save() {
		System.out.println("save方法执行...");
		return "saveOK";
	}
	
	public String update() {
		System.out.println("update方法执行...");
		return NONE;
	}
}

struts.xml

<!-- 演示Action之间的跳转  
			  注意:跳转路径写匹配好的Action的name即可
		 -->
		<action name="Demo3Action_*" class="cn.ahpu.action.Demo3Action" method="{1}">
			<result name="saveOK" type="redirectAction">Demo3Action_update</result>
		</action>

index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
  </head>
  
  <body>
    <a href="${ pageContext.request.contextPath }/demo1/demo1.jsp">demo1</a><br>
    <a href="${ pageContext.request.contextPath }/Demo3Action_save.action">Action之间跳转测试</a>
  </body>
</html>

访问 ${ pageContext.request.contextPath }/Demo3Action_save.action

果然先执行save再执行update

暂时就演示3个

 

二、struts2专门的数据封装  ★

Action类中写属性,提供get/set,框架自动帮你封装数据,还用得着啥子servlet api? 强大!!

 

1.属性驱动方式(封装到Action内定义的属性里)

Action中定义属性 只用给属性添加set方法  然后框架的拦截器就自动帮你封装好了  属性name就是前端数据的name

demo2.jsp

<h3>属性驱动方式封装数据</h3>
		<form action="${ pageContext.request.contextPath }/regist1.action" method="post">
        	姓名:<input type="text" name="username" /><br/>
        	密码:<input type="password" name="password" /><br/>
        	年龄:<input type="text" name="age" /><br/>
                <input type="submit" value="注册" />
		</form>

struts.xml

<!-- 新包 测试数据封装  一般一个项目一个包就够了 -->
	<package name="demo2" namespace="/" extends="struts-default">
		<action name="regist1" class="cn.ahpu.action.Regist1Action"/>
	</package>

Regist1Action.java

package cn.ahpu.action;

import com.opensymphony.xwork2.ActionSupport;

/**
 * 数据封装方式demo
 * 属性驱动
 */
public class Regist1Action extends ActionSupport {
	
	//设置属性 只用给属性添加set方法  然后框架的拦截器就自动帮你封装好了,封装到了这些属性中
	private String username;
	private String password;
	private String age;
	public void setUsername(String username) {
		this.username = username;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public void setAge(String age) {
		this.age = age;
	}


	@Override
	public String execute() throws Exception {
		System.out.println("name:"+username+"\n"+"pwd:"+password+"\nage:"+age);
		return NONE;
	}
}

 

2.属性驱动方式(封装到action的类成员变量里 前端要写OGNL麻烦 )(了解即可

action内定义个属性,属性本身是个javabean 提供get/set  自己new不用提供set

demo2.jsp  注意name写法

	<h3>属性驱动方式封装数据(Action内new一个javabean 直接封装到javabean对象中)</h3>
		<form action="${ pageContext.request.contextPath }/regist2.action" method="post">
			<!-- 注意name写OGNL表达式 语法类似OGNL -->
        	姓名:<input type="text" name="user.username" /><br/>
        	密码:<input type="password" name="user.password" /><br/>
        	年龄:<input type="text" name="user.age" /><br/>
                <input type="submit" value="注册" />
		</form>

struts.xml

<action name="regist2" class="cn.ahpu.action2.Regist2Action"/>

User.java

package cn.ahpu.action2;

public class User {
	private String username;
	private String password;
	private Integer age;
	//省略get set
	@Override
	public String toString() {
		return "User [username=" + username + ", password=" + password
				+ ", age=" + age + "]";
	}
	
}

 

Regist2Action.java

package cn.ahpu.action2;

import com.opensymphony.xwork2.ActionSupport;

/**
 * 数据封装方式demo
 * 属性驱动
 */
public class Regist2Action extends ActionSupport {
	
	private User user=new User();//自己new了就不需要提供set了
	public User getUser() {
		return user;
	}

	@Override
	public String execute() throws Exception {
		System.out.println(user);
		return NONE;
	}
}

 

3.模型驱动(前端name值不用写OGNL,也可封装到javaBean类对象中)

模型驱动 最简单常用  实现一个接口  前端正常写  后端Action实例化一个javabean对象为属性 不需要get/set

模型驱动的方式
    1.实现ModelDriven接口
    2.手动实例化对象(需要自己new好)

前端demo2.jsp 写法没啥特殊之处了

<h3>属性驱动方式封装数据(模型驱动方式 不用改前端,也可封装数据到对象中)</h3>
		<form action="${ pageContext.request.contextPath }/regist3.action" method="post">
        	姓名:<input type="text" name="username" /><br/>
        	密码:<input type="password" name="password" /><br/>
        	年龄:<input type="text" name="age" /><br/>
                <input type="submit" value="注册" />
		</form>

struts.xml

<action name="regist3" class="cn.ahpu.action2.Regist3Action"/>

User.java同上

Regist3Action.java

package cn.ahpu.action2;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

/**
 * 数据封装方式demo
 * 模型驱动的方式
 *  1.实现ModelDriven接口
    2.手动实例化对象(需要自己new好)
 */
public class Regist3Action extends ActionSupport implements ModelDriven<User>{
	
	private User user=new User();//必须自己new好
	//不用提供get/set 但必须实现这个方法     拦截器会调用这个必须实现的方法获取user对象,帮助你封装数据   多简单
	@Override
	public User getModel() {
		return user;
	}

	@Override
	public String execute() throws Exception {
		System.out.println("模型驱动"+user);
		return NONE;
	}
	
}

 

4.数据封装到集合 list和map 能封装到List<User>和Map<String,User> 但是前端仍然要写OGNL,麻烦。不学了

 

三、拦截器

拦截器只能对Action请求起作用(Action中的方法),而过滤器可以对几乎所有的请求起作用(CSS JSP JS)

需要在struts.xml中进行拦截器的配置,配置一共有两种方式,学第一种即可
 

1.编写拦截器类,关键:继承

DemoInterceptor.java

package cn.ahpu.interceptor;

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

public class DemoInterceptor extends AbstractInterceptor {

	/**
	 * 配置好后,执行action方法之前会执行intercept
	 */
	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		System.out.println("Action方法执行之前");
		String invoke = invocation.invoke();//表示执行下一个拦截器(Struts2就是一大堆拦截器组成的) 
		System.out.println("Action方法执行之后");
		return invoke;//返回值必须这么写  不放行就卡死在这了
	}

}

2.编写一个新的action方法

UserAction.java

package cn.ahpu.action3;

import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport{
	@Override
	public String execute() throws Exception {
		System.out.println("我是UserAction的方法...");
		return NONE;
	}
}

3.配置拦截器(自定义拦截器,action引入自定义的拦截器) ★

struts.xml拦截

<?xml version="1.0" encoding="UTF-8" ?>
	<!DOCTYPE struts PUBLIC
		"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
		"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
	<package name="struts02" namespace="/" extends="struts-default">
		
		<!-- 下面两个action的跳转一模一样,删除,在外面配置一个全局的即可 
			效果:此struts02包下所有action的方法return success; 都会根据此配置跳转
				当然,若下面的action内还是自己配置了<result name="success">  会覆盖掉全局的
		-->
		<global-results>
			<result name="success" type="redirect">/demo1/suc.jsp</result>
		</global-results>
	
		<action name="demo1Action" class="cn.ahpu.action.Demo1Action">
			<!-- <result name="success">/demo1/suc.jsp</result> -->
		</action>
		
		<action name="demo2Action" class="cn.ahpu.action.Demo2Action">
			<!-- <result name="success">/demo1/suc.jsp</result> -->
		</action>
		
		<!-- 演示Action之间的跳转  
			  注意:跳转路径写匹配好的Action的name即可
		 -->
		<action name="Demo3Action_*" class="cn.ahpu.action.Demo3Action" method="{1}">
			<result name="saveOK" type="redirectAction">Demo3Action_update</result>
		</action>
	</package>
	
	<!-- 新包 测试数据封装  一般一个项目一个包就够了 -->
	<package name="demo2" namespace="/" extends="struts-default">
		<action name="regist1" class="cn.ahpu.action2.Regist1Action"/>
		<action name="regist2" class="cn.ahpu.action2.Regist2Action"/>
		<action name="regist3" class="cn.ahpu.action2.Regist3Action"/>
	</package>
	
	<!-- 新包,测试拦截器的使用 -->
	<package name="demo3" namespace="/" extends="struts-default">
		<!-- package内action外定义拦截器-->
		<interceptors>
			<!-- name随便写  class必须是你写的那个Interceptor类的全路径 -->
			<interceptor name="DemoInterceptor" class="cn.ahpu.interceptor.DemoInterceptor"/>
		</interceptors>
	
		<action name="user" class="cn.ahpu.action3.UserAction">
			<!-- 引入自定义拦截器 -->
			<interceptor-ref name="DemoInterceptor">
				<!-- 放行写法  中间可以写写此不拦截的此action的方法-->
				<!-- <param name="excludeMethods">login,regist,checkCode</param> -->
			</interceptor-ref>
			<!-- 只要引入了自定义拦截器,默认栈的拦截器就不执行了,必须手动引入 -->
			<interceptor-ref name="defaultStack"/>
		</action>
	</package>
	
</struts>

4.测试运行

 

今日重点:

使用ServletActionContext类(原生Servlet的API的方式)(好用,掌握)★    [ServletActionContext.getRequest()]
属性驱动方式(封装到Action内定义的属性里)★                                        [Action内定义基本属性,提供get/set自动封装]
模型驱动(前端name值不用写OGNL,也可封装到javaBean类对象中)★  [Action实现ModelDriven接口,实现getModel]
拦截器★                                                               [写Interceptor类实现接口,xml内先定义拦截器,再action内引入拦截器]

 

 

 

 

 

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐