Struts2培训笔记

7.25
---------
struts2

mvc开发模式

struts2是一个mvc框架

struts2与struts1
struts2封装了WebWork

struts2框架的优点
 提高了Action组件的灵活性(摆脱了框架api,Servlet容器的api的依赖性)
 提供了多种视图技术的整合
 提供拦截器和拦截器栈

struts2框架的主要结构
核心控制器
使用过滤器实现
实现组件为
 struts2.1.8版本以前使用
 org.apache.struts2.dispatcher.FilterDispatcher	 

 从struts2.1.8开始
 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter 

Action组件
 普通的JavaBean,可以选择继承或者不继承框架api

Result组件
 用于衔接视图响应技术,如jsp,freemarker,stream,json,表格,图表等

Interceptor组件(拦截器组件)
 用于封装通用的功能,可以在Action业务方法执行前后处理

struts2核心jar包
 struts2-core.jar

struts2框架配置
 Struts-default.xml(内置)
  在struts2-core.jar包下
  作用:预订义了一些Result组件Interceptor组件,拦截器栈

 xml定义结构
  <bean>元素,用于创建JavaBean对象时,为底层注入信息
  <package>元素,用于存放Result,Interceptor,Action组件的定义
  <result-types>元素,用于定义Result组件
  <interceptors>元素--【拦截器】,用于定义interceptor和interceptor-stack组件
  <action>元素,用于定义Action组件

 struts.xml(自定义):DTD模板(struts2-core-2.1.8/struts-2.1.7.dtd)必须要有的
  要求定义在类加载路径下,配置结构和struts-default.xml相同
  作用:自定义定义的Result组件,Interceptor组件,Action组件

 default.properties(内置)
  struts-core-2.1.8.jar-org.apache.struts2包下
  作用:定义与框架相关的系统属性,如字符编码,请求后缀名等

 struts.properties(自动义) 不是必须要有的  
   定义在类加载路径下

使用需要修改内置的default.properties中的值有两种方法:
方法一:
 struts.properties 中 key=value 如:struts.action.extension=do
方法二:
 struts.xml中:
 <constant name="struts.action.extension" value="do"></constant>


获得web组件
方法一:
 ActionContext
 代码:
Map<String, Object> session 
	= ActionContext.getContext().getSession();
Map<String, Object> application 
	= ActionContext.getContext().getApplication();
Map<String, Object> request 
	= (Map<String, Object>)ActionContext.getContext().get("request");

适配器模式:底层就是HttpSession

方法二:
ServletActionContext

HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession();
HttpServletResponse response = ServletActionContext.getResponse();
ServletContext application = ServletActionContext.getServletContext();

方法三:
XxxAware

public class BaseAction extends ActionSupport implements ServletRequestAware,ServletResponseAware,ServletContextAware,SessionAware

XxxAction extends BaseAction

XxxAction 可以直接使用request response application seesion 对象

ActionSupport--返回值可以大写【SUCCESS = "success"】


struts.xml详细配置
修改default.properties(内置)中的值:
 <constant name="struts.action.extension" value="do"></constant>

<include>元素:相对路径 类加载器路径,作用就是包含其它的xml文件
 <include file="struts-member.xml"></include>
 <include file="struts-manager.xml"></include>

<package>元素:namespace
 /member/login.jsp
 /menager/login.jsp
 Action组件对应的请求格式:协议://ip:port/应用名/namespace名/Action组件名.后缀名
 
action中method没写,默认执行execute方法(ActionSupport中的方法)
result中的name 没写:默认值是SUCCESS
result中的type没写:默认是转发【default-struts】

<param>元素:用于为包含他的对象注入信息
使用:Action中提供属性,提供get set方法

从Action中读值
<result>${path}</result>

7.26
-------
通配符*
<action>元素的name属性可以使用*,表示任意字符
其他属性可以使用{1},{2}....{N}引用第N个*代表的信息

例子:
<action name="opt_*" class="action.OptAction" method="{1}">
	<result>/index.jsp</result>
</action>
url访问路径:http://localhost:8080/struts2-1/user/opt_add.action


<action name="opt_*_*_*" class="action.{1}Action" method="{2}" >
	<result>/{3}.jsp</result>
</action>

url访问路径:http://localhost:8080/struts2-1/user/opt_Opt_add_success.action


直接访问WEB-INF下的jsp文件
例子:
<action name="show">
	<result>/WEB-INF/a.jsp</result>
</action>

<action name="show_*">
	<result>/WEB-INF/{1}.jsp</result>
</action>

动态方法调用
请求格式
namespace名/Action名!业务方法名.后缀名

例子:
请求路径:http://localhost:8080/struts2-1/user/opt!add.action
<action name="opt" class="action.OptAction">
	<result>/index.jsp</result>
</action>

struts2标签+ognl表达式
ognl开源项目【Object Graphic Navigation Language 对象图导航语言】

作用:通过一个字符串对对象进行操作

jar包:ongl.jar 在WebWork以前就存在
了解Ognl API
 getValue(String expression,Map context,Object root);
 setValue(String expression,Object root,Object value);

<%@ taglib uri="/struts-tags" prefix="s"%>

作用:
 可以访问对象属性  语法:对象.属性
 可以访问对象方法  语法:对象.方法()
 可以访问类中静态成员【静态方法 属性 内部类】 语法:@包名.类名@静态成员名
 可以对集合进行过滤操作 
    [n] 	返回下标为n的元素
    #this	表示集合中每一个元素
    ?		返回满足条件的所有元素
    ^		返回满足条件的第一个元素		
    $		返回满足条件的第最后一个元素
    %{}		先计算后取值
    .{}		对集合筛选

struts2中ValueStack结构
 Map context			request,session,application,parameter,临时变量
 CompoundeRoot root栈结构	放Action对象

struts2将Ongl方法分成了2个方法
 findString context
 findValue root

package org.apache.struts2.dispatcher;
public class StrutsRequestWrapper extends HttpServletRequestWrapper{
	public Object getAttribute(String key){
		Object val=super.getAttribute(key);
		if(val==null){
			//从Action的属性取值
			val=valuestack.findValue(key);
		}
		return val;
	}
}

class HttpServletRequestWrapper implements HttpServletRequest{
	
	private HttpServletRequest request;

	

	getAttribute(){
		return request.getAttribute();
	}

	setAttribute(){
		request.setAttribute();
	}

	getParamerter(){
		request.getParamerter();
	}
}

EL表达式问题:
 Struts2允许在页面使用EL表达式访问Action中的数据,
 原因是struts2将HttpServletRequets的实例封装了,
 并且重写了getAttribute方法,
 先调用super.getAttribute();
 如果找不到再访问ValueStack中root区域Action的属性

例子:
使用EL显示Action中name属性:${name }<br/>
使用EL显示Action中的msg属性:${msg }<br/>
name:<s:property value="name"/><br/>
msg:<s:property value="msg"/>
代码获得msg:
<% 
	String msg = (String)request.getAttribute("name");
	if(null != msg)
	{
		out.print(msg);
	}
%>
<br/>
request:<s:property value="#request"/><br/> <!-- 结果是map结构 -->
requets.msg:<s:property value="#request.msg"/><br/>
emp.name:<s:property value="emp.name"/><br/>
emp.name:${emp.name }<br/>
emp.name:<s:property value="emp.name.toUpperCase()"/><br/>
request.get("msg"):<s:property value="#request.get('msg')"/><br/>
PI:<s:property value="@java.lang.Math@PI"/><br/>
ls中下标为1的值:<s:property value="ls[1]"/><br/>
emps中满足id>4的所有元素:<s:property value="emps.{?#this.id>4}.{#this.id}"/><br/>
<!-- ognl本省要求%{}先计算后取值,struts2优化了,可以不写 -->
ls中小表为i+1的元素:<s:property value="%{ls[i+1]}"/>


iterator
if
else
elseif

date

例子:
<s:iterator value="emps" var="e" status="s">
<tr>
	<td><s:property value="#s.count"/></td>
	<td><s:property value="#e.id"/></td>
	<td><s:property value="#e.name"/></td>
	<td>
		<s:if test="#e.salary >= 10000">
			<font color="green">
		</s:if>
		<s:else>
			<font color="red">
		</s:else>
		<s:property value="#e.salary"/>
		</font>
		
	</td>
	<!--<td><s:property value="#e.birthday"/></td>-->
	<td><s:date name="#e.birthday" format="yyyy年MM月dd日"/></td>
</tr>
</s:iterator>

其它标签
<% 
	request.setAttribute("abc","abc");
%>
<s:a action="list" namespace="/vs" encode="utf-8">
	<s:param name="aaa" value="123"></s:param>
	<s:param name="bbb" value="#request.abc"></s:param>
	<s:param name="ccc" value="'abc'"></s:param>
	<s:param name="ddd" value="'啊'"></s:param>
	list
</s:a>

<s:url action="list" namespace="/vs">
	<s:param name="aaa" value="abc"></s:param>
</s:url>

<s:action name="list" namespace="/vs" executeResult="false">
	<s:param name="aaa" value="abc"></s:param>
</s:action>

<%--set标签用于向指定的范围设置一组值request,sessionapplication,context --%>
<s:set var="i" value="10" scope="request"></s:set>
<s:set var="str" value="'abc'"></s:set> <!-- 默认是context区域 -->
<s:set var="hobbies" value="{'吃','玩','睡'}"></s:set> <%-- {}表示数组 --%>
<s:set var="person" value="#{'name':'aaa','age':23}"></s:set><%-- #{}表示map --%>
<s:debug></s:debug>

<s:property value="#person.name"/><br/>
<s:iterator value="#person">
	<li><s:property value="key"/>=<s:property value="value"/></li>
</s:iterator>




表单标签
<s:form action="form" namespace="/form" theme="xhtml">
		<s:textfield name="username" label="username"></s:textfield>
		<s:textfield name="email" label="email"></s:textfield>
		<s:password name="password" showPassword="true" label="password"></s:password>
		<s:textarea name="description" label="description" cols="50" rows="10"></s:textarea>
		<s:hidden name="h" value="abc"></s:hidden>
		<!-- checkbox中的value值是true和false 默认不写 写和默认值一样 默认会选中 -->
		<s:checkbox name="mycheck" value="true" label="是否同意"></s:checkbox>
		<!-- list ognl表达式 里面是map或者对象 a是提交的值,aa是显示的值 -->
		<s:checkboxlist list="#{'a':'aa','b':'bb'}" name="c" label="ccc"></s:checkboxlist>
		<!-- 提交的值是id 显示的值name -->
		<s:checkboxlist list="emps" name="e" label="e" listKey="id" listValue="name"></s:checkboxlist>
		<!-- choise.a 集合中的键为a -->
		<s:checkbox name="choise.a" value="a" label="a"></s:checkbox>
		<s:checkbox name="choise.b" value="b" label="b"></s:checkbox>
		<s:checkbox name="choise.c" value="c" label="c"></s:checkbox>
		<!-- emp.id emp对象中的id属性 -->
		<s:textfield name="emp.id" label="id"></s:textfield>
		<s:textfield name="emp.name" label="name"></s:textfield>
		<s:textfield name="emp.salary" label="salary"></s:textfield>
		
		<s:radio list="#{'1':'男','0':'女'}" name="sex" label="sex"></s:radio>
		<!-- 提供一个空元素emptyOption -->
		<s:select list="#{'1':'a','2':'b','3':'c'}" name="s" label="s" headerKey="-1" headerValue="---请选择---"></s:select>
		<!-- 分组下拉框 -->
		<s:select list="{}" label="ss">
			<s:optgroup label="aaa" list="#{'1':'a','2':'b','3':'c'}"></s:optgroup>
			<s:optgroup label="bbb" list="#{'4':'d','5':'e','6':'f'}"></s:optgroup>
		</s:select>
		<s:submit value="submit" />
	</s:form>



重定向到Action
<result type="redirectAction">
	<param name="actionName">form!showForm</param>
	<param name="namespace">/form</param>
	<param name="method">showForm</param>
</result>
转发到Action
<result type="chain">
	<param name="actionName">form</param>
	<param name="namespace">/form</param>
	<param name="method">showForm</param>
</result>

表单数据校验
-------
数据格式检查分为客户端和服务器端两种
客户端:使用js,特点相应速度快,对客户友好,服务器压力小 缺点:安全性差
服务器端:使用服务器编程语言 特点:安全性高,其它全是缺点

50w以上考虑服务器端验证

使用struts2创建实现表单数据格式校验
1、基于java代码,表写校验规则
	
 a:Action继承ActionSuppor,重写validate方法
    在validate方法中可以使用addFieldError方法中添加错误消息
 b:在struts.xml配置Action时,需要定义name为input的result
 c:input指定的result页面中,可以使用<s:fielderror>标签显示错误消息
   表单标签也具有显示错误消息的功能,theme="xhtml"

  注意:一个action的validate方法对所有action中的方法校验。
  所以:Action中存在多个业务方法,
	  不同的业务方法需要不同的校验逻辑
	  可以使用validateXxx()命名格式的方法来校验
	  Xxx为业务方法名,首字母大写

   检验流程的条用顺序:
   获得请求数据-->类型转换-->setter-->
   validateXxx()-->validate()-->业务方法
                             -->result name="input"
 @Override
    public void validate()
    {
        System.out.println("validate()....");
        if("".equals(username))
        {
            this.addFieldError("username", "用户名不能为空!");
        }
        if("".equals(password))
        {
            this.addFieldError("password", "密码不能为空");
        }
    }

2、基于xml配置,使用预订义好的校验器
   xml文件和Action放在同一个包下
   xml文件命名:	
	Action类型-validation.xml
	Action类型-请求名-validation.xml

   xml文件遵守dtd规范(xwork-core-2.1.6/xwork-validator-1.0.3.dtd)
   xml校验配置分为字段型风格和非字段型风格

校验规则:
文件路径
(xwork-core-2.1.6.jar-
com.opensymphony.xwork2.validator.validators
-default.xml)

required		非String类型使用,检查是否为空 
requiredstring		String类型使用,检查是否为空
int			范围检查
long			范围检查
short			范围检查
double			范围检查
date			范围检查
expression		非字段风格,跟ognl表达式匹配
fieldexpression		字段风格,跟ognl表达式匹配
email			email格式检查,可以为空
url			url格式检查 ,可以为空
visitor			用于检查复合类型 user.username
conversion		
stringlength		字符串长度检查
regex			正则表达式匹配
conditionalvisitor



非字段型
<validators>
  <validator type="requiredstring">
  	<param name="fieldName">username</param>
  	<message>用户名不能为空</message>
  </validator>
  
  <validator type="requiredstring">
  	<param name="fieldName">password</param>
  	<message>密码不能为空</message>
  </validator>
  
  <validator type="stringlength">
  	<param name="fieldName">password</param>
  	<param name="maxLength">6</param>
  	<param name="minLength">2</param>
  	<message>密码位数必须在${minLength}-${maxLength}位之间</message>
  </validator>
</validators>

字段型
<field name="username">
	<field-validator type="requiredstring">
		<message>用户名不能为空</message>
	</field-validator>
</field>

<field name="password">
	<field-validator type="requiredstring">
		<message>密码不能为空</message>
	</field-validator>
	<field-validator type="stringlength">
		<param name="minLength">3</param>
		<param name="maxLength">7</param>
		<message>密码位数在${minLength}-${maxLength}之间</message>
	</field-validator>
</field>

7.30
I18N 国际化

需要国际化的有:日期 数字 文字

java中需要使用这个类ResourceBundle来操作properties文件

文件编写格式:
xxx.properties
xxx_语言编码_国家编码.properties

struts2中 JSP,Action,validation.xml中的文字要做国际化

需要修改的key值 default.propreties中
struts.custom.i18n.resources

struts.xml配置 找到properties的文件
<constant name="struts.custom.i18n.resources" value="文件的位置">

JSP中使用国际化
使用<s:text name="" />

文本框中的label中文,把label换成key 其它标签一样
<s:textfield key="">

代码:
<s:text name="a"></s:text>
<s:textfield key="a"></s:textfield>
<!--i18n标签可以指定访问哪种语言,所包含的都不访问本地语言-->
<s:i18n name="i18n.info_en_US">  
	<s:text name="a"></s:text>
	<s:textfield key="a"></s:textfield>
</s:i18n>

Action中国际化【Action必须要要继承ActionSupport】
String s = this.getText("");

validation.xml中国际化
<message key="a"></message>

国际化 日期 数字 文字
Java代码:

//日期
Date date = new Date();
System.out.println(date);
//格式化日期 getDateTimeInstance 会调用Locale.getDefault()
DateFormat format = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
System.out.println(format.format(date));
//获得当前默认的语言
System.out.println(Locale.getDefault());
//获得计算机所有语言
Locale[] locales = Locale.getAvailableLocales();
for(Locale locale:locales)
{
    System.out.println(locale.getCountry()+" "+locale.getLanguage());
}

//数字
double d = 2131231321313.23;
NumberFormat format1 = NumberFormat.getNumberInstance();
System.out.println(format1.format(d));
//货币
format1 = NumberFormat.getCurrencyInstance();
System.out.println(format1.format(d));

//获得文件的路径
URL url = Test.class
                .getClassLoader()
                .getResource("i18n/info.properties");
System.out.println(url);
Test.class
.getClassLoader()
.getResourceAsStream("i18n/info.properties");


//相对于src路径
ResourceBundle rb = ResourceBundle.getBundle("i18n/info");
System.out.println(rb.getString("a"));;

//        Properties p=new Properties();
//      p.load(in);
//      
//      System.out.println(p.getProperty("a"));



异常处理:
 手动异常
 业务异常 
	this.addActionError("用户名或密码错误");
 Action异常 
	Action中抛出异常
	struts默认不处理异常 需要配置struts.xml
	<exception-mapping result="userNotFound" exception="excption.UserNotFoundException"></exception-mapping>

	<result name="userNotFound">/login1.jsp</result>
	jsp中获取异常消息
	<s:property value="exception.message"/>

全局异常 当前包中都可以用  顺序不能反 
不同的包 有相同的异常 也可以写在单独的包 其它包extends继承使用
<global-results>
	<result name=""></result>
</global-results>
<global-exception-mappings>
	<exception-mapping result="" exception=""></exception-mapping>
</global-exception-mappings>

配置文件properties
 预订义的配置文件
 	struts.properties 整个应用可以访问
	package.properties 当前包有效
	Action类名.properties  当前action有效
 自定义的配置文件
	struts.properties
	struts.xml

属性类型转换
 struts2框架默认支持的类型:
	String String[] List<String>
	基本类型 包装类型 List<包装类型>
	ognl表达式表示的复合类型 如:user.username
 自定义【其它类型】
  	编写规则 写个类继承StrutsTypeConverter
	类加载路径下   
		创建xwork-conversion.properties
		类型=规则
        在国际化文件中
		创建Action类名.properties文件
		写入:invalid.fieldvalue.xxx=消息【xxx表示属性名】
		

获得请求数据-->类型转换-->setter-->validateXxx()-->validate()-->业务方法
		   --->conversionError拦截器负责处理错误消息-->result name="input"

拦截器
 拦截器的作用
  用于在执行Action组件业务处理之前和之后调用
  可以将和业务处理相关的通用处理封装成拦截器,
  从而达到服用以及模块化管理
  AOP
 	
 自定义拦截器
  编写拦截器类,实现Interceptor接口或者继承AbstractInterceptor
	String methodName = invocation.getProxy().getMethod();
        HttpServletRequest request = ServletActionContext.getRequest();
	//执行下一个组件,将下一个组件的返回值返回或者将下一个组件的异常返回
	String result = invocation.invoke();
  在struts.xml中配置拦截器
	包中
	<interceptors>
		<interceptor name="log" class="interceptor.LogInterceptor">
		</interceptor>
	</interceptors>
  引用拦截器
   action中<interceptor-ref name="log"></interceptor-ref>

  注意:如果Action显示引用自定义拦截器,默认的拦截器不起作用
  在引用默认包中的拦截器 <interceptor-ref name="defaultStack"></interceptor-ref>

  方法过滤功能的拦截器
   要求:拦截器类继承MethodFilterInterceptor类
	在struts.xml中配置拦截器
	引用拦截器
<interceptor name="checkLogin" class="interceptor.CheckLoginInterceptor"></interceptor>

<interceptor-stack name="checkLoginStack">
	<interceptor-ref name="defaultStack"></interceptor-ref>
	<interceptor-ref name="checkLogin">
		<param name="includeMethods">execute*,modify*,remove*</param>
		<param name="excludeMethods">add*</param>
	</interceptor-ref>
</interceptor-stack>

面向过程
面向对象
面向接口
面向切面
面向惯例

了解内置拦截器:
autowiring 自动装配拦截器:
	主要用于当struts2和spring整合时,struts2可以使用自动装配方式
	来访问spring容器中的Bean
chain链拦截器:构建一个Action链,放到ValueStack的root区域,
	      和<result type="chain"> 一起使用
conversionError转换错误拦截器:负责处理类型转换错误的拦截器
clearSession清除Session拦截器:负责销毁HttpSession对象
createSession创建Session拦截器:负责创建一个HttpSession对象
exception异常拦截器:将Action抛出的异常映射到结果
fileUpload文件上传拦截器:用于处理文件上传
i18n国际化拦截器:负责把用户所选的语言和区域存放到Session中
params参赛交互过滤拦截器:最基本的拦截器,负责解析Http请求中的数据,
			并注入到Action中,必须要有。
staticParams静态参数拦截器:负责将xml文件中Action标签下的<param>
				标签中的参数注入到Action
token令牌拦截器:负责阻止表单重复提交
tokenSession令牌会话拦截器:负责阻止表单重复提交
validation验证拦截器:负责处理XxxAction-validation.xml校验
workflow工作流拦截器:负责处理validate()方法校验
checkbox复选框拦截器:负责处理复选框提交的数据设置成boolean类型


fileUpload拦截器
struts2中的Action代码

private File f;
private String fFileName;

public String execute() throws Exception {
		System.out.println(name);
		String path = application.getRealPath("upload");
//		FileUtil.copy(f, path+"/"+fFileName);
		 f.renameTo(new File(path,fFileName));
		return SUCCESS;
	}

Util包
public class FileUtil {

	public static void copy(File src,String dest)
	{
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			bis = new BufferedInputStream(new FileInputStream(src));
			bos = new BufferedOutputStream(new FileOutputStream(dest));
			byte[] b = new byte[2048];
			int i;
			while((i=bis.read(b)) != -1)
			{
				bos.write(b,0,i);
			}
			
		} catch (Exception e) {
			
		}
		
	}
}	

7.31
----------
限制上传文件的类型
struts.xml配置
<action name="upload" class="action.UploadAction">
	<interceptor-ref name="fileUpload">
		<param name="allowedExtensions">.txt,.ppt</param>
	</interceptor-ref>
	<interceptor-ref name="defaultStack"></interceptor-ref>
	<result>/upload.jsp</result>
	<result name="input">/upload.jsp</result>
</action>

name值:maximumSize  allowedTypes allowedExtensions

消息错误,配置国际化,编写properties文件
key有四种:
struts.messages.error.file.extension.not.allowed
struts.messages.error.content.type.not.allowed	
struts.messages.error.file.too.large 
struts.messages.error.uploading


token/tokenSession拦截器【防止表单重复提交】
客户端:提交按钮后设置按钮为disable不可用,IE浏览器要加一步手动提交表单

服务器:用验证码来防止表单重复提交

默认的defaultStack中没有token拦截器

token用法:
struts.xml中引用taken拦截器
jsp中 写一行代码 <s:token></s:token>
报404  用result重新指向一个页面

tokenSession区别:不报404自己会访问上一次页面

struts.xml代码:
<action name="token" class="action.TokenAction">
	<interceptor-ref name="defaultStack"></interceptor-ref>
	<interceptor-ref name="tokenSession"></interceptor-ref>
	<result>/index.jsp</result>
<!--<result name="invalid.token">/index.jsp</result>-->
</action>


Result组件
-----------
执行完Action后执行Result组件

 案例:输出JSON数据
 自定义:
 编写Result实现类,使用Result接口或继承StrutsResultSupport
 需要jar包:json-lib-2.1.jar
 
步骤:
JSONResult代码:
1、获得Action对象
Object action = invocation.getAction();
2、将Action中的数据转换成json字符串
String jsonStr = JSONUtil.toJson(action);
3、获得response对象
HttpServletResponse response=ServletActionContext.getResponse();
4、设置response的contentType text/json;charset="utf-8";
response.setContentType("text/json;charset=utf-8");
5、将json字符串写回给客户端
PrintWriter out = response.getWriter();
out.write(jsonStr);
out.flush();

Action:中提供数据就行
struts.xml中代码:
<result-types>
<!--<result-type name="json" class="result.JSONResult"></result-type>-->
	<result-type name="json" class="org.apache.struts2.json.JSONResult"/>
</result-types>

<action name="json" class="action.JSONAction">
	<result type="json">
		<param name="root">emp</param><!--只显示emp对象中的数据-->
	</result>
</action>


官方包中提供了转换JSON的Result组件
struts2-json-plugin-2.1.8.jar-struts-plugin.xml
<result-type name="json" class="org.apache.struts2.json.JSONResult"/>

相关使用
get方法上加
@JSON(serialize=false)  JSON字符串中不显示该属性
@JSON(name="name") 修改显示的名字

Result组件
-----------
web组件:dispatcher redirect
Action组件:chain redirectAction

chain的原理:是valueStack将两个action同时放入到root区域

Action中要有相同的属性 属性共享

struts.xml相关配置
<action name="a1" class="action.A1Action">
	<result type="chain">
		<param name="actionName">a2</param>
	</result>
</action>

<action name="a2" class="action.A2Action">
	<result>/chain.jsp</result>
</action>


stream
---------
做下载功能:
name=inputName--告诉struts下载哪个流下面的文件
	【当action有两个以上的输入流时,如果名字为InputStream时不许要写,莫恶人是这个】
attachment--附件意思

代码:
Action:
private InputStream fstream;
private String fileName;

public String execute() throws Exception {
	
	String path=application.getRealPath("WEB-INF/tomcat_admin.rar");

	fstream=new FileInputStream(path);

	fileName="tomcat.rar";

	return SUCCESS;
}

struts.xml配置:
<action name="download" class="action.DownloadAction">
	<result type="stream">
		<param name="inputName">fstream</param><!--必须要写-->
		<param name="contentDisposition">attachment;filename=${fileName}</param>
		<param name="bufferSize">2048</param>
	</result>
</action>


做验证码:
Action中代码:
private InputStream imageSteam;
private String s = "0123456789abcdefghigkinmopqrstuvwxyz";

public String execute()throws Exception
{
        BufferedImage image = new BufferedImage(80, 30, BufferedImage.TYPE_INT_BGR);
        Graphics graphics = image.getGraphics();
        graphics.setColor(Color.red);
        graphics.fillRect(0, 0, 80, 30);
        graphics.setColor(Color.yellow);
        graphics.setFont(new Font("宋体", Font.BOLD+Font.ITALIC, 20));
        StringBuffer sb = new StringBuffer();
        Random random = new Random();
        for(int i=0;i<5;i++)
        {
            int index = random.nextInt(s.length());
            sb.append(s.charAt(index));
        }
        graphics.drawString(sb.toString(), 8, 25);
        session.put("code",sb.toString());
        ByteArrayOutputStream dest = new ByteArrayOutputStream();
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(dest);
        encoder.encode(image);
        imageSteam = new ByteArrayInputStream(dest.toByteArray());
        
        return SUCCESS;
}

JSP中代码:
<script type="text/javascript">
function changePic()
{
	document.getElementById("image").src = "${pageContext.request.contextPath }/result/image.action?time="+new Date().getTime();
}
</script>

<a href="javascript:;" οnclick="changePic()">
<img id="image" alt="" src="${pageContext.request.contextPath }/result/image.action">
</a>

struts.xml中的代码:
<action name="image" class="action.ImageAction">
	<result type="stream">
		<param name="inputName">imageSteam</param>
	</result>
</action>

<action name="checkCode" class="action.CheckCodeAction">
	<result>/index.jsp</result>
	<result name="fail">/image.jsp</result>
</action>

补充
------------------
eclipse添加dtd文件:
window-preferences-xml(搜索)-xml catalog

extension 扩展名

重定向:两次请求
转发:一次请求

servlet 实例化两种情况(第一次调用,服务器启动[<load-on-startup>])

servlet生命周期:初始化-init(有参)

数字精确计算,尤其是银行系统计算
BigDecimal b1 = new BigDecimal("12.345");
BigDecimal b2 = new BigDecimal("12");
System.out.println(b1.subtract(b2));  //0.345

BigInteger i1 = new BigInteger("123132131231231312312313123");
BigInteger i2 = new BigInteger("123132131231231312312313123");
System.out.println(i1.subtract(i2)); //0

//告诉容器,以utf-8编码解析请求体中的数据
request.setCharacterEncoding("utf-8");
//告诉浏览器,以utf-8编码解析响应数据,并以utf-8编码打开
response.setCharacterEncoding("utf-8");
//告诉容器,响应数据格式为text/html的编码为utf-8,并且以utf-8编码传输
//以utf-8编码解析响应数据,并以utf-8编码打开
response.setContentType("text/html;charset=utf-8");

get请求数据在请求头中 只有iso8859-1字符集
post请求数据在请求体中

<%@include file="/index.jsp"> //编译期间
<jsp:include page="/index.jsp"></jsp:include>

进入字符串代码:选中字符串-ctrl+shirt+t

转发到另一个action type=“china”
重定向到另一个action type="redirectAction"

properties 只有一个字符编码 iso8859-1 不能写中文 能写中文是myeclipse装了插件

cmd native2ascii 注册  ==  \u6CE8\u518C

当前文件-rt.jar-环境变量
file相对路径是 相对运行java程序的路径
Test.class.getClassLoader().getResource();

js中的调用方法传参问题:
for(var i=0;i<arguments.length;i++)
{
	alert(arguments[i]);
}


随机产生[a,b]
(int)(Math.random()*(b-a+1))+a;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值