Struts2

  1. Struts2框架的基本使用
  2. Struts2工作原理以及核心思想
  3. Struts2 知识点梳理

Struts2简介

Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互

配置文件

//web.xml   配置Struts2过滤器,拦截所有请求,将请求统一交给Struts2管理
<filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
</filter-mapping>
//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="user" namespace="/user" extends="struts-default">
        <action name="UserAction" class="cn.it.UserAction" method="register">
    	    <result name="success">/hello.jsp</result>
            <result name="error">/error.jsp</result>
        </action>
    </package>
</struts>

package元素:
   将Action配置封装,可在package中配置多个Action
   name属性:package包的名字,起到标识作用
   namespace属性:给action的访问路径定义一个命名空间
   extends属性:继承一个指定包,加载其已经配好的配置,必选
action元素:
   配置action类
   name属性:决定Action访问资源名
   class属性:action的完整类名
   method属性:指定调用action中的哪个方法来处理请求
result元素:
   结果配置
   name属性:表示结果处理的名称,与action方法的返回值对应
   type属性:指定调用哪个result类来处理结果,默认使用转发dispatcher,重定向redirect
   标签体:填写jsp页面的相对路径

struts2常量配置
struts2默认常量配置在核心包下的default.properties
修改常量配置:
方式1(重点):struts.xml根元素<struts>下添加

<!-- 以下为默认配置 -->
<!-- 解决post提交乱码 -->
<constant name="struts.i18n.encoding" value="UTF-8"></constant>
<!-- 指定访问action时的后缀名,默认是action或空 -->
<constant name="struts.action.extension" value="action,,"></constant>
<!-- 指定struts2是否以开发模式运行
		1.热加载主配置.(不需要重启即可生效)
		2.提供更多错误信息输出,方便开发时的调试
 -->
<constant name="struts.devMode" value="false"></constant>

方式2:src下创建struts.properties进行配置
方式3:web.xml中添加

<context-param>
	<param-name>struts.i18n.encoding</param-name>
	<param-value>UTF-8</param-value>
</context-param>

配置进阶

动态方法调用

//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">

<!-- 方式1(了解):配置动态方法调用常量,默认是关闭的,访问路径/dynamic/DemoAction!add -->
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>

<struts>
    <package name="dynamic" namespace="/dynamic" extends="struts-default">
    	<!-- (了解)如果找不到包下的action,会使用Demo2Action作为默认action处理请求 -->
    	<default-action-ref name="Demo2Action"></default-action-ref>
        <!-- 方式2:使用通配符
		使用{1}取出第一个*通配的内容,访问路径/dynamic/DemoAction_add
         -->
        <action name="DemoAction_*" class="cn.it.DemoAction" method="{1}">
    	    <result name="success">/hello.jsp</result>
            <result name="error">/error.jsp</result>
        </action>
    </package>
</struts>

配置文件的默认值(了解)
method=“execute”
result的name=“success”,type=“dispatcher”

Action类

action书写方式
方式1:创建一个类,可以是POJO
使struts2框架的代码侵入性更低
方式2:实现Action接口,里面有execute方法,提供action方法的规范
Action接口预置了一些字符串,可以在返回结果字符串时使用,为了方便

方式3(常用):继承ActionSupport类
帮我们实现了Action,Validateable,ValidationAware,TextProvider,LocaleProvider接口
如果需要用到这些接口的实现时,就不需要自己来实现了

结果处理方式

  1. 转发
<result name="success" type="dispatcher">/hello.jsp</result>
  1. 重定向
<result name="success" type="redirect">/hello.jsp</result>
  1. 转发到Action
<!-- 需要先在/命名空间下配好DemoAction -->
<result name="success" type="chain">
	<param name="actionName">DemoAction</param>
	<!-- 指定该Action所在的命名空间 -->
	<param name="namespace">/</param>
</result>
  1. 重定向到Action
<result name="success" type="redirectAction">
	<param name="actionName">DemoAction</param>
	<param name="namespace">/</param>
</result>

struts2获得servletAPI

1.ActionContext
struts2提供了一个类,存放了servlet相关的所有对象,相当于数据中心,本质上是一个Map
原生request      HttpServletRequest
原生response     HttpServletResponse
原生ServletContext   ServletContext
request域       Map
session域       Map
application域      Map
param参数       Map request.getParameterMap
attr域         Map 三个域合并(request域/session域/application域)
ValueStack      值栈

ActionContext的生命周期:每次请求时,都会创建一个与请求对应的ActionContext对象.请求处理完,ActionContext销毁.

ActionContext对象被创建后,struts2会将ActionContext对象与当前线程绑定,只需要从ThreadLocal中获取即可.

//request域=>map (struts2不推荐使用原生request域,由ActionContext代替)
//不推荐
Map<String,Object> requestScope = (Map<String,Object>) ActionContext.getContext().get("request");
//推荐
ActionContext.getContext().put("name","request");
//session域=>map
Map<String,Object> sessionScope = ActionContext.getContext().getSession();
sessionScope.put("name","session");
//application域=>map
Map<String,Object> applicationScope = ActionContext.getContext().getApplication();
applicationScope.put("name","application");

在StrutsPrepareAndExecuteFilter中,struts2对原生request进行代理,改变原有getAttributes()方法,在request域取值后会继续到ActionContext中取值,jsp中el表达式底层是调用request的getAttributes(),因此同样可以取到ActionContext中的值.

2.ServletActionContext
ServletActionContext是一个工具类,用于方便从ActionContext数据中心取对象

//原生request
HttpServletRequest request = ServletActionContext.getRequest();
//原生session
HttpSession session = request.getSession();
//原生response
HttpServletResponse response = ServletActionContext.getResponse();
//原生servletContext
ServletContext servletContext = ServletActionContext.getServletContext();

struts2框架希望脱离原生servlet,所以并不推荐使用该方式

3.Action类实现ServletRequestAware等接口
接口会传递原生request对象,在拦截器中通过ActionContext获取request对象,调用重写接口方法传递

struts2参数获得方式

1.属性驱动

public class DemoAction extends ActionSupport {
	//与表单参数键同名的属性
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public String execute() throws Exception {
		System.out.println(name);
		return SUCCESS;
	}
}

引申:Servlet中不能使用属性接收参数,因为serlvet线程不安全,servlet在运行期间只会创建一个实例,多个用户同时访问时,都会对该变量进行赋值.因此把接收参数的变量放到方法中,在方法内声明变量接收参数,多个线程调用同一个方法,会分别创建一个方法区,独立运行.

每次请求Action时,都会创建新的Action实例对象,线程安全,因此可以使用成员变量(八大基本数据类型及对应包装类)接收参数.也支持用Date类型接收yyyy-MM-dd格式的字符串参数.

属性驱动在现实开发中不常用,因为需要对每一个成员变量设置getset方法,当参数较多时,会比较麻烦.

2.对象驱动

//需要准备一个User类,jsp的表单项name值设为user.name/user.age等,即可将参数封装到user对象中
public class DemoAction extends ActionSupport {
	private User user;
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
	
	public String execute() throws Exception {
		System.out.println(user);
		return SUCCESS;
	}
}

3.模型驱动

//Action类实现ModelDriven接口,jsp的表单项name值设为name/age/...,即可将参数封装到user对象中
public class DemoAction extends ActionSupport  implements ModelDriven<User>{
	//准备user成员变量,需要手动new一个
	private User user = new User();
	
	public String execute() throws Exception {
		System.out.println(user);
		return SUCCESS;
	}

	@Override
	//返回需要封装参数的对象
	public User getModel() {
		return user;
	}
}

集合类型参数封装

//封装集合类型参数(类似属性驱动)
//list:jsp表单提交项的name值设为list/list[1]/list[2]/...(list可多个,按顺序装入集合)
//map:jsp表单提交项的name值设为map['aa']/map['bb']/...
public class DemoAction extends ActionSupport {
	private List<String> list;
	
	private Map<String,String> map;
	
	public String execute() throws Exception {
		System.out.println(list);
		System.out.println(map);
		return SUCCESS;
	}

	public List<String> getList() {
		return list;
	}
	public void setList(List<String> list) {
		this.list = list;
	}
	map get set
}

OGNL表达式

OGNL:Object-Graph Navigation Language.对象视图导航语言 (EL也是对象视图导航,从11大内置对象中取值)
补充:EL表达式中,param和requestScope的区别
OGNL不仅仅可以视图导航,还支持比EL表达式更加丰富的功能
OGNL从OGNL Context(上下文)对象中取值
Ognl表达式基本原理和使用方法

ValueStack

Struts2与OGNL表达式的结合:ValueStack值栈(相当于OGNLContext)
Root部分是一个栈(底层是由list实现),可以放置多个对象,默认情况下,栈中放置当前访问的Action对象
Context部分就是ActionContext数据中心
在取root栈中的属性时,会从栈顶开始找属性,若找不到,依次往下找
数据中心ActionContext与值栈ValueStack是互相引用
struts2中的值栈对象ValueStack
ValueStack值栈和ActionContext

//获得值栈
ValueStack vs = ActionContext.getContext().getValueStack();
vs.push(Object);

在JSP页面中获取ValueStack数据

<%@ taglib prefix="s" uri="/struts-tags" %>
<!-- 查看值栈中Root和Context部分的内容 -->
<s:debug></s:debug>

1.参数接收
  属性驱动:页面传递参数"name=tom",在经过struts2框架的params拦截器时,会被交给ognl处理,执行表达式"name=tom",则会在Root栈中的当前访问Action对象内查找name属性并赋值,即通过属性驱动完成参数接收.
  对象驱动:页面传递参数"user.name=tom",栈顶对象Action中要有user属性,同样通过ognl表达式完成赋值.
  模型驱动:页面传递参数"name=tom",在ognl表达式执行前,因为Action实现了ModelDriven接口,其getModel()返回一个user对象,该user对象会被modelDriven拦截器(位于params拦截器前)压到栈顶,则name属性会被user对象接收.

2.配置文件中使用ognl
struts.xml中可以使用${ognl表达式},从ValueStack中取值.例如在redirectAction重定向到另一个Action时,可以附带参数.

<action name="DemoAction" class="cn.it.DemoAction">
	<result name="success" type="redirectAction">
		<param name="actionName">Demo2Action</param>
		<param name="namespace">/</param>
		<!-- 传递参数,struts会将无法识别的param作为参数附加在重定向的路径之后 -->
		<param name="name">${name}</param>
	</result>
</action>

在StrutsPrepareAndExecuteFilter中,就会完成ValueStack/ActionContext对象的创建,还会包装request对象的getAttribute(String)方法,先从原生request域取值,若无,则先后在ValueStack的栈和ActionContext部分取值.

struts标签

普通标签:控制标签和数据标签
UI标签:表单标签和非表单标签
控制标签:iterator 与c标签的foreach功能相同
if elseif else

<s:if test="#list.size()==4">
	liist长度为4
</s:if>
<s:elseif test="#list.size()==3">
	liist长度为3
</s:elseif>
<s:else>
	xxxxx
</s:else>

数据标签:property.用来配合ognl表达式在页面取值.与el表达式功能相同

<s:property value="#list.size()"/>
<s:property value="#session.user.name"/>

表单标签:用于生成表单.
form.textfield.password.radio.submit(略)
非表单标签:actionerror

//Action中添加错误信息
this.addActionError("错误信息");
<s:actionerror/>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!-- #表示从ActionContext取值,每次循环会将list中的对象按顺序取出,并压到值栈栈顶 -->
<s:iterator value="#list">
	<!-- property标签用于书写ognl表达式从值栈取值,若不写value属性,则直接取栈顶属性 -->
	<s:property value="name">
	<s:property value="level">
	<s:property value="phone">
</s:iterator>

<!-- 若使用var属性,则会将集合中对象放入ActionContext,键为var值 -->
<s:iterator value="#list" var="cust">
	<!-- property标签用于书写ognl表达式从值栈取值 -->
	<s:property value="#cust.name">
	<s:property value="#cust.level">
	<s:property value="#cust.phone">
</s:iterator>

异常处理/拦截器

配置全局异常处理,抛出异常后,会根据异常类类型返回相应字符串结果.

throw new RuntimeException("密码错误!");

抛出的异常信息会被压到栈顶,在jsp页面通过struts标签可以取出

<s:property value="exception.message"/>

自定义拦截器类
方式1.实现Intercepter接口,重写init/intercept/destroy方法.
方式2.继承AbstractInterceptor.其已经空实现了init和destory方法,只需要实现intercept方法
方式3.继承MethodFilterInterceptor.实现doIntercept方法.(推荐)

//继承:MethodFilterInterceptor 方法过滤拦截器
//功能: 定制拦截器拦截的方法.
//	定制哪些方法需要拦截.
//	定制哪些方法不需要拦截
public class MyInterceptor extends MethodFilterInterceptor{
	@Override
	protected String doIntercept(ActionInvocation invocation) throws Exception {
		//前处理
		System.out.println("MyInterceptor 的前处理!");
		//放行
		String result = invocation.invoke();
		//后处理
		System.out.println("MyInterceptor 的后处理!");
		return result;
	}
}

拦截器配置:1.注册拦截器 2.注册拦截器栈 3.指定包中的默认拦截器栈

<?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>
	<constant name="struts.devMode" value="true"></constant>
	<package name="crm" namespace="/" extends="struts-default" >
		<interceptors>
			<!-- 注册拦截器 -->
			<interceptor name="loginInterceptor" class="cn.itheima.web.interceptor.LoginInterceptor"></interceptor>
			<!-- 注册拦截器栈 -->
			<interceptor-stack name="myStack">
				<interceptor-ref name="loginInterceptor">
					<param name="excludeMethods">login</param>
				</interceptor-ref>
				<interceptor-ref name="defaultStack"></interceptor-ref>
			</interceptor-stack>
		</interceptors>
		<!-- 指定包中的默认拦截器栈 -->
		<default-interceptor-ref name="myStack"></default-interceptor-ref>
		<!-- 定义全局结果集 -->
		<global-results>
			<result name="toLogin" type="redirect" >/login.jsp</result>
		</global-results>
		<global-exception-mappings>
			<!-- 如果出现java.lang.RuntimeException异常,就将跳转到名为error的结果 -->
			<exception-mapping result="error" exception="java.lang.RuntimeException"></exception-mapping>
		</global-exception-mappings>
		
	
		<action name="CustomerAction_*" class="cn.itheima.web.action.CustomerAction" method="{1}" >
			<result name="list" >/jsp/customer/list.jsp</result>
			<result name="toList" type="redirectAction">
	             <param name="actionName">CustomerAction_list</param>
	             <param name="namespace">/</param>
	         </result>
		</action>
		<action name="UserAction_*" class="cn.itheima.web.action.UserAction" method="{1}" >
			<result name="toHome" type="redirect" >/index.htm</result>
			<result name="error"  >/login.jsp</result>
		</action>
	</package>
</struts>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值