Struts2综合笔记

strust2导包
commons-beautils           [beanutils工具包]
					commons-filupload.ajr       [文件上传]
					commons-io.jar  
					commons-lang         [struts2对java.lang.*类的支持]
					freemarker.jar        [视图显示技术]
					javassit              [struts2对字节码运算的支持]
					ognl.jar             [struts2对ognl表达式的支持]
				       struts2-core.jar       [ struts2的核心包 ]
				      xwork-core.jar	   [webwork框架的支持,struts2的前身就是webwork(对webwork的封装)]
					
Struts2配置:  即在WebRoot\WEB-INF\web.xml配置全局过滤器StrutsPrepareAndExecuteFilter	
<!--  配置启动strut2的全局过滤器 -->
	<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>
struts2框架简介
			strurs2是基于MVC开发模型的web层框架。
			struts1也是MVC开发模式的框架。struts2并不是struts1的升级版。
			struts2是基于webwork的升级版。struts2=webwork+sturts1
struts-default.xml文件解析
默认包,包名叫struts-default(我们自己写的package必须继承这个默认包,只有继承了这个默认包才可以使用该默认包下的功能)
<package name="struts-default" abstract="true">			
跳转类型result-type 申明,目前共10种 :
Dispatcher,Chain,Freemarker,Httpheader,Redirect,redirectAction,Stream,Velocity,Xslt,plaintext,

拦截器(Interceptor)
拦截器(Intercptor)和 过滤器(Filter)
				过滤器: 可以过滤任何类型的请求(html、servlet、jsp)和响应。加入通用的代码逻辑。
				拦截器: 是sturts2的特有功能。只能过滤Action!!在执行Action的时候加入通用的代码。
默认拦截器栈:<interceptor-stack name="defaultStack">    				
默认包当前使用的拦截器:<default-interceptor-ref name="defaultStack"/>
我们写的包(package)就是继承struts-default默认包的,那么就继承了默认拦截器栈的所有拦截器
					
struts.xml文件详解:(package),用于管理Action,一般可以按模块划分包:
<?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" extends="struts-default" namespace="/" abstract="false">
			<action name="login1" class="com.example.test.LoginAction">
				<result name="success" type="redirectAction">book</result>
			</action>
			<action name="login2" class="com.example.test.LoginAction" method="login2">
				<result name="login" type="dispatcher">/login2.jsp</result>
			</action>
		</package>
</struts>
package: 代表一个包。管理action配置。在用一个包下面不能有同名的action。
package的属性:
name: 包名.在一个项目中不能出现同名的包。
extends:  继承。我们开发的包就必须继承struts-default包。
namespace:  名称空间。区分不同的包的访问路径。默认值  “/” 
	    abstract: 是否抽象。是抽象包,不能含有action.	抽象包中用来定义拦截器,公共视图,不做具体的业务。	
action配置:
			  name:  action的名称。用于访问该Action的路径 ,不能重复
			  class:  Action业务对象的类名。一定是全名(包名+类名)			  
method: 执行的业务方法。不写默认值 execute
result配置:
		name: 处理方法的返回值	          	
type: 跳转的类型	

struts2的Action实现三种使用方式
第一种方式,不实现Action接口
public class UserAction2 {
	public String login()throws Exception{
		System.out.println("UserAction2.login()");
		return "success";
	}	
}						
第二种方式:实现Action接口
/**  1)定义了默认的execute方法的标准
 *   2)提供了项目中常用的视图标记 */
public class UserAction implements Action {
	public String login() throws Exception {
		System.out.println("执行了UserAction的login方法");
		return SUCCESS;
	}
	public String execute() throws Exception {
		return null;
	}
}
第三种方式: 继承ActionSupport类(推荐使用)
 /* *  1)提供了常用的视图标记
 * 	2)提供了数据校验功能 */
public class UserAction3 extends ActionSupport{
	public String login()throws Exception{
		System.out.println("UserAction3.login()");
		return SUCCESS;
	}
}

路径通配符:可以只配置一个action来匹配多个要执行的方法
一个模块(Action对象)使用一个action配置
<action name="user_*" class="com.example.UserAction" method="{1}">
			<result name="{1}">/{1}.jsp</result>
		</action>
* (星号) :表示路径的通配符,在配置文件中会自动替换成匹配成功的请求路径中对应的字符串   
{1}:表示获取第一个通配符的实际内容,下面以{1}匹配的内容为方法名,jsp文件名  
		
多个模块使用一个action配置
	如果*_*匹配User_login.  则第一个*代表模:User,第二个*代表方法:login. /{1}/{2}.jsp表示 /User/login.jsp
		 <action name="*_*" class="com.example.{1}Action" method="{2}">
			<result name="{2}">/{1}/{2}.jsp</result>
		 </action>

strus2的常量配置
	指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法 和freemarker 、velocity的输出 
    <constant name="struts.i18n.encoding" value="UTF-8"/>
    自定义后缀:    <constant name="struts.action.extension" value="do"/>
    设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 
    <constant name="struts.serve.static.browserCache" value="false"/>
    当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 
    <constant name="struts.configuration.xml.reload" value="true"/>
    开发模式下使用,这样可以打印出更详细的错误信息 
    <constant name="struts.devMode" value="true" />
    默认的视图主题 
    <constant name="struts.ui.theme" value="simple" />
    与spring集成时,指定由spring负责action对象的创建 
    <constant name="struts.objectFactory" value="spring" />
    该属性设置Struts 2是否支持动态方法调用,默认值是true。使可以通过!method访问action的方法
    <constant name="struts.enable.DynamicMethodInvocation" value="false"/> 
    上传文件的大小限制 
<constant name="struts.multipart.maxSize" value=“10701096"/>

全局视图配置
全局视图作用: 当该包下的所有action都使用到的一些视图就是可以放到全局视图配置中
			   当action中也有相同名称的视图,那么action的局部视图会覆盖全局视图。
全局视图配置: 把该包下的所有action共用的视图都机集中在这里写 
	 <global-results>
		<result name="success">/login.jsp</result>
	 </global-results>
action的默认配置:
name: 必填项
class: 可选项.默认配置:  
ActionSupport类   该类继承自struts-default (<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />)
method: 可选。默认执行excute()
			    result:
			    	name: 可选。默认配置: success
			    	type: 可选。默认配置: dispatcher
	全部使用默认配置的action的作用 :专门用于转发到WEB-INF下的页面
	 <action name="login">
		<result>/WEB-INF/jsp/login.jsp</result>
	</action>
		
Action的属性注入:把Action对象中需要把一些经常改变的参数提取到配置文件中
Action属性注入的步骤
			1)在Action类中声明一个成员变量,用于接收xml配置文件传入内容
			2)在Action类提供一个该变量的setter方法,该方法接收了xml配置的内容
private String savePath;//成员变量
public void setSavePath(String savePath) {//提供属性的setter方法,用于外部的action的参数进行注入
		this.savePath = savePath;
	}
在对应的struts.xml文件中,找到对应的action对象的配置,然后在action中使用
<action name="upload" class="com.example.test" method="upload">
	<param name="savePath">e:/images/</param>
	<result>/login.jsp</result>
</action>
				
sruts2的数据共享的三种方式
第一种方式
	ServletActionContext类
		ServletActionContext.getRequest():获取Request对象:request.setAttribute("key", value)
		ServletActionContext.getRequest().getSession() :获取Session对象:session.setAttribute("key", value)
		ServletActionContext.getServletContext() :获取ServletContext对象servletContext.setAttribute("key", value)
		该方式依赖servlet的api,耦合比较高

第二种方式
	ActionContext类:ActionContext actionContext = ActionContext.getContext();
		actionContext .getContextMap():获取操作request域对象数据的map集合
		actionContext .getSession():获取操作session域对象数据的map集合	
		actionContext .getApplication():获取操作context域对象数据的map集合
		不依赖servlet的api,耦合性低
		actionContext对象在Action对象被Struts2创建后,才被框架创建		
第三种方式	
RequestAware,SessionAware,ApplicationAware 接口
不依赖servlet的api
可以在Action对象的所有方法中共享Map集合

sruts2请求参数数据的封装
1.直接赋值给简单数据类型			
public class UserAction extends ActionSupport{
	//参数赋值(注入方式)
	private String name; //变量名要和jsp页面的name值一一对应
	private String password;
	private String gender;
	private String[] hobit;
	//参数通过这个set方法注入到Action中
	public void setName(String name) {
		this.name = name;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	public void setHobit(String[] hobit) {
		this.hobit = hobit;
	}


2.赋值给一个javabean对象
<form action="${pageContext.request.contextPath }/data/user_register.action" method="post">
    	用户名: <input type="text" name="user.name"/><br/>
    	密码: <input type="password" name="user.password"/><br/>
    	性别: <input type="radio" name="user.gender" value="男"/>男
    	 <input type="radio" name="user.gender" value="女"/>女<br/>
    	爱好:
    	<input type="checkbox" name="user.hobit" value="篮球"/>篮球
    	<input type="checkbox" name="user.hobit" value="足球"/>足球
    	<input type="checkbox" name="user.hobit" value="羽毛球"/>羽毛球<br/>
    	<input type="submit" value="注册"/>
</form>
public class UserAction2 extends ActionSupport{
	private User user; //使用一个javabean对象接收,变量名要和jsp页面的name一一对应

	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
3.赋值给javabean对象还可以通过ModelDriven
请求参数的封装通过struts2的ParametersInterceptor拦截器进行赋值.
action执行的时候会先执行validate方法对参数进行一些列的验证,如果他发现当前对象包含fieldError信息,就会直接给你跳转到input视图

自定义类型转换
作用: 默认情况下,页面的日期类型只能接收 yyyy-MM-dd类型,如果要转换yyyy/MM/dd这种类型,则需要使用自定义类型转换器进行转换。
strut2提供了自定义类型转换器的基类: StrutsTypeConverter
创建配转换数据类型需要的置文件:UserAction-conversion.properties_bak(action类名-)  
文件中写入:user.birth=com.example.test.MyDateConverter(全类名)
public class MyDateConverter extends StrutsTypeConverter{
	SimpleDateFormat  sdf1 = new SimpleDateFormat("yyyy/MM/dd");
	/** 从页面的数据到服务器的类型转换
	 * 参数一: context: 值栈上下文对象
	 * 参数二: values:  从页面传递过来的参数值
	 * 参数三: toClass: 转换到的类型。String->java.util.Date*/
	@Override
	public Object convertFromString(Map context, String[] values, Class toClass) {
		//写相关逻辑代码
	}
	/** 从服务器到页面的类型转换*/
	@Override
	public String convertToString(Map context, Object o) {
		return null;
	}
}

绑定自定义转换器的方式:
方式一: 局部绑定(只能绑定一个Action)
	1)建立一个 Action的文件名-conversion.properties
	2)一定和绑定的Action放在同一个目录下。
方式二: 全局绑定(绑定整个项目多个Action)
	1)建立一个xwork-conversion.properties  写入:java.util.Date=com.example.MyDateConverter(转换累的类全名)
	2)该文件一定放在src目录下。		

文件上传和下载
文件上传三个条件: 
			Form中有input  并且input的type属性为file
			post提交
			enctype="multipart/form-data"

在Action中接收文件内容
		File attach;   (attach是file表单的name属性值 必须对应)
		String attachContentType;  文件类型(固定写法)
		String attachFileName;   文件名称(固定写法)
<!-- 修改默认文件最大上传大小值 -->
	<constant name="struts.multipart.maxSize" value="100000000"></constant>
					修改允许上传的文件类型和文件后缀
	<action name="upload" class="com.example.UploadAction" >
				<!-- 往FileUploadInterceptor拦截器的属性注入值(调用setter方法) -->
			 	<interceptor-ref name="defaultStack">
			 		<!-- 改变当前文件上传拦截器的允许文件类型 -->
			 		<param name="fileUpload.allowedTypes">image/jpeg,image/jpg</param>
			 		<!-- 允许的文件后缀 -->
			 		<param name="fileUpload.allowedExtensions">jpg,jpeg,gif</param>
			 		<!-- 如果以上配置都写了,那么取他们的交集  -->
			 	</interceptor-ref>
				<param name="savePath">e:/images/</param>
				<result>/login.jsp</result>
				<result name="input">/error.jsp</result>
</action>				
下载主要配置:
<action name="down_*" class="com.example.DownAction" method="{1}">
				<param name="serverPath">e:/images/</param>
				<result name="list">/listFile.jsp</result>
				<result name="down" type="stream">
					 <param name="contentType">application/octet-stream</param> //字节流
  					 <param name="inputName">inputStream</param> //action类中要提供对应的方法
  					 <param name="contentDisposition">attachment;filename=${name}</param>//告知下载文件名
   					 <param name="bufferSize">1024</param>//文件缓存大小
				</result>
</action>	

拦截器:拦截器类似于过滤器的功能,过滤器可以过滤项目的任何请求(servlet/jsp/html/img),拦截器只能拦截Action请求。	
定义拦截器interceptor的三种方式 :
1.实现Interceptor接口 实现必须的三个方法
           init() :拦截器初始化  服务器启动时候就初始化所有需要的拦截器
           intercept(ActionInvocation invocation): action访问的时候执行 如果不放行直接返回,就跳到结果页面
	      destroy():销毁	服务器停止的时候销毁	
2.继承AbstractInterceptor 类,已经实现了init和destroy方法
3.继承MethodFilterInterceor  :可以指定不需要拦截的方法
申明和使用拦截器:			
<package name="inter" extends="struts-default" namespace="/inter">
	    	<!-- 申明拦截器:拦截器在此申明后,在web服务器启动的时候就会被初始化 -->
	    	<interceptors>
	    		<interceptor name="inter1" class="com.example.MyInterceptor1"></interceptor>
	    	</interceptors>
	    	<action name="user_*" class="com.example.UserAction" method="{1}">
	    		<!-- 申明该action使用该拦截器:使用后,访问该action的请求,会先经过拦截器 -->
	    		<interceptor-ref name="inter1"></interceptor-ref>
	    		<result>/index.jsp</result>
	    	</action>
 </package>
拦截器生命周期:
	 1.启动服务器时候,申明在配置文件的拦截器,被初始化,调用init方法 
2.执行该拦截器的intercepot方法拦截。在action目标方法 invocation.invoke()执行前后,写相应的业务逻辑。	
     4.当服务器停止时,拦截器对象才被销毁		
拦截器作用范围:
1.局部使用:在action内部使用,只作用于该action						
<action name="user_*" class="com.example.UserAction" method="{1}">
	    		<!-- 使用拦截器 -->
	    		<interceptor-ref name="inter1"></interceptor-ref> 
	    		<result>/index.jsp</result>
</action>
2.全局使用: 当package内,action外使用 作用于package内的所有action
<package name="inter" extends="struts-default" namespace="/inter">
	    	<!-- 申明拦截器 -->
	    	<interceptors>
	    		<interceptor name="inter1" class="com.example.MyInterceptor1"></interceptor>
	    	</interceptors>
	    	<!-- 使用截器 -->
	    	<default-interceptor-ref name="inter1"></default-interceptor-ref>
</package>
拦截器栈:包含多个已经申明的拦截器。拦截器和拦截器栈都在interceptors标签内申明				
	<interceptors>
	    	<interceptor name="inter1" class="com.example.MyInterceptor1"></interceptor>
	    	<interceptor name="inter2" class="com.exampler.MyInterceptor2"></interceptor>
	    	<!-- 定义栏截器栈 -->
	    	<interceptor-stack name="interStack">
	    		<interceptor-ref name="inter1"></interceptor-ref>
	    		<interceptor-ref name="inter2"></interceptor-ref>
	    	</interceptor-stack>
</interceptors>	
拦截器栈中拦截器的执行顺序:先配置先初始化
	1.创建拦截器inter1对象,调用init方法
	2.创建拦截器inter2对象,调用init方法
	3.执行inter1的interceptor方法前面代码
	4.执行inter2的interceptor方法前面代码
	5.Action的业务方法		
	6.执行inter2的interceptor方法后面代码
	7.执行inter1的interceptor方法前面代码
注意:当我们的包下引用了自定义拦截器栈,则会把默认包下的default-stack拦截器给覆盖掉	
      为了不覆盖默认拦截器,所以自定义的拦截器栈要加入Struts2默认的拦截器栈:	
<interceptor-stack name="myStack">
	    			<interceptor-ref name="defaultStack"></interceptor-ref><!-- 引入了默认的全部拦截器 -->
	    			<interceptor-ref name="interStack"></interceptor-ref><!-- 引入自定义的2个拦截器 -->
</interceptor-stack>		
struts2的主要初始化流程:
1.创建StrutsPrepareAndExcuteFilter对象,执行init方法
2.加载default.properties配置文件 
3.加载struts-default.xml  struts-plug.xml struts.xml配置文件
4.初始化Struts默认配置的拦截器和自定义的拦截器,调用init方法
struts2的处理请求的主要流程:
如果请求目标是action ,Struts2框架拦截器才会处理,WebRoot下的静态资源是不会经过拦截器的。
1.依次执行对目标action起作用的拦截器的 intercept(ActionInvocation invocation)方法
2.调用actionInvocation .invocation()方法放行
3.创建目标action对象,调用目标方法,目标方法返回配置文件result需要的字符串标记,
4.根据目标方法返回的标记,跳到下一个action或者直接返回给浏览器result视图


值栈
 OGNL(Object Graphic Navigation Languag的缩写,它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。
在struts2项目中导入ognl.jar包来实现支持ognl表达式。
ognl表达式和EL表达式:
EL表达式: 获取域对象的数据。 不能存放数据,不能调用方法
Ognl表达式: 获取域对象的数据。  可以存放数据,可以调用方法。
OGNL的优势:
1.支持对象方法调用,如xxx.doSomeSpecial(); 
2.支持类静态的方法调用和值访问,表达式的格式:
    @[类全名(包括包路径)]@[方法名 |  值名],例如:
    @java.lang.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME; 
3.支持赋值操作和表达式串联,如price=100, discount=0.8,
             calculatePrice(),这个表达式会返回80; 
4.访问OGNL上下文(OGNL context)和ActionContext; 
5.操作集合对象。
			

Ognl表达式核心OgnlContext对象
从OgnlContext对象取出根对象数据(ognlContext .setRoot(object)保存的数据),不需要#号
从OgnlContext对象取出非根对象数据(ognlContext .put(key, object)保存的数据),需要#号


struts2的值栈(ValueStack)对象(对OgnContext对象的封装)
ValueStack接口,的实现类OgnlValueStack
ValueStack的数据存储结构:分为List栈(根栈)和Map栈(非根栈)
			1)List栈主要存储Action对象和Provider代理对象,自定义对象	
			2)Map栈主要存放各个域存放的数据和用户的参数信息
   域对象的List中的取值语法:域对象.对象变量名.对象变量名...,域对象可以省略
   域对象的Map中的取值语法:#域对象.map的key,域对象可以省略

jsp页面获取值栈(ValueStack)List中和Map中的数据数据:	
1. <%@ taglib uri="/struts-tags" prefix="s"%>   //申明使用Struts标签 并且以s为前缀使用
2.<s:property value="user.name"/> - <s:property value="user.age"/> //取出valueStack 中的List保存的数据
  3.<s:property value="#request.request_data"/>  //根据map的key取出request域中map储存的数据
  4. <s:property value="#request_data"/><br/>   //从request域的map中取数据可以省略request
5.<s:property value="#session.session_data"/>  //根据map的key取出session域中map储存的数据
6.<s:property value="#application.application_data"/> //根据map的key取出application域中map储存的数据
  7.<s:property value="#attr.session_data"/> // #attr.key 从request域,session域,application域的map中依次一查找
  8.<s:property value="#parameters.name"/>  //获取客户端传过来的name参数的值

迭代域对象中map储存的List
<s:iterator value="#request.userList" var="user">
        <s:property value="#user.name"/> 
</s:iterator>

迭代域对象中map储存的map
<s:iterator value="#request.userMap" var="entry">
    <s:property value="#entry.key"/>
    <s:property value="#entry.value.name"/>
</s:iterator>
在action中的成员变量 如果提供了该成员变量的getter方法,该成员变量在获取时会自动被加入到valueStack中
使用s:property 获取ValueStack中的数据。 所有以变量名+点的方式获取数据,要在在action和对象中提供相应的get方法

文字国际化
	国际化的资源文件命名规则:
		包名_语言简写_国家简称.properties
		中国: message_zh_CN.propertiesjava
		美国: message_en_US.properties
		英国:  message_en_GB.properties	
		不同国家的资源包命名:
		中国: message_zh_CN.properties
		美国:  message_en_US.properties
		英国:  message_en_GB.properties	

在struts.xml文件中指定国际化资源包的加载路径:			
<constant name="struts.custom.i18n.resources" value="resources.message"></constant>
在jsp页面上使用: <s:text name="user"/> //其中user就是key值,所有同一字符串不同语言的key值是相同的,value不同
					
struts2数据验证拦截器:
<interceptor name="validation" class="com.opensymphony.xwork2.validator.ValidationInterceptor"/>
1.代码验证Action类被访问的方法被访问前数据是否合法
01.Action类继承ActionSupport(以实现Validatable接口)
02.Action类覆盖validate方法(覆盖该方法会对所有访问的action方法生效)
03.在struts.xml文件中对应的action配置加上input视图,接收错误信息
04.验证Action类的指定方法规则(不覆盖validate):validate+需要验证的方法名称:
	 例如:验证register()方法,则需要在该action类下面创建validateRegister()方法验证
代码:
01.验证时候如果出现错误信息则:super.addFieldError("user.name", "用户名不能为空!");
02.验证完后Struts2框架会查看错误信息集合,如果有数据则直接转发到input视图,不再执行目标方法
     03.在input指定的jsp页面,用<s:fielderror fieldName="user.name"></s:fielderror>获取自己定义的错误信息

2.xml配置文件验证Action类被访问的方法被访问前数据是否合法
01.在Action类文件的同一目录下,编写一个xml文件
02.名称:Action类文件名-validation.xml(对所有被访问的方法生效)
03.名称:Action文件名-访问方法路径-validation.xml
	例如: UserAction类的register方法: urld的访问路径是user_register  
文件名为:UserAction-user_register-validation.xml
    Struts2定义的action配置文件约束类型验证器的路径是:
/com/opensymphony/xwork2/validator/validators/default.xml

Struts2标签库:
 1.流程控制标签
 2.数据标签
 3.UI标签
struts2表单标签:
	<!-- theme:指定表单的主题,xhtml:默认simple:没有主题 -->
	<s:form action="Demo3Action" namespace="/" theme="xhtml" >
		<s:textfield name="name" label="用户名"  ></s:textfield>
		<s:password name="password" label="密码" ></s:password>
		<s:radio list="{'男','女'}" name="gender" label="性别" ></s:radio>
		<s:radio list="#{1:'男',0:'女'}" name="gender" label="性别" ></s:radio>
		<s:checkboxlist list="#{2:'抽烟',1:'喝酒',0:'烫头'}" name="habits" label="爱好" ></s:checkboxlist>
		<s:select list="#{2:'大专',1:'本科',0:'硕士'}" headerKey="" headerValue="---请选择---" name="edu" label="学历" >
		</s:select>
		<s:file name="photo" label="近照" ></s:file>
		<s:textarea name="desc" label="个人简介" ></s:textarea>
		<s:submit value="提交" ></s:submit>
	</s:form>

默认情况下,struts2不支持防止重复提交的
1.在struts.xml文件中打开功能:
<interceptors>
			<interceptor-stack name="myStack">
				<interceptor-ref name="defaultStack"></interceptor-ref>
				<interceptor-ref name="token"></interceptor-ref>
			</interceptor-stack>
</interceptors>					
2.jsp页面指定一个标签:<s:token></s:token>

   					




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值