Struts2的一些基本用法笔记
2018-03-11 10:22
393 查看
4000
Struts2基本
——————————————————————————————————
Struts2的常量配置方法(常量默认值在struts2-core-版本号.jar下org/apache/struts/default.porperties中可找到)
1、配置struts.xml(常用)
例如在struts.xml中指定资源文件
<struts>
…..
<constant name=”struts.custom.il8n.resources”value=”Name”>
…..
</struts>
2、修改struts.properties
3、配置web.xml
Struts2框架有特定的加载配置常量的顺序,后加载的同名常量将被覆盖,先后顺序struts.xml > struts.properties > web.xml
另外在struts.xml中可以通过<includefile=”fileName.xml”/>导入其他配置文件,这可以使struts.xml不会太庞大杂乱,能对其进行模块管理
————————————————————————————————————————————————
实现Action
Aciton是struts的核心,主要对用户请求进行逻辑处理
Action类不需要继承任何的struts基类或者实现任何接口
对请求而言,Action可以没有对应的实例变量,但需要包含变量名对应的getter/setter
但Action有一个默认的实现类ActionSupport,该类继承了Action、Validateable接口,通过继承ActionSupport会使开发更加规范和简单
同时ActionSupport类也是没有定义处理类(<class=””>)的action默认处理类
————————————————————————————————————————————————
访问ServletAPI
通过ActionContext访问Servlet API
主要通过ActionContext实现,可以通过该类的getContext()静态方法获取实例
通过该类实例可以访问/修改application、session、request范围的属性
这里有一个问题是一般获取表单请求参数(不是request属性)时,getParameters()的返回是一个Map(String,Parameter)类型
使用map.get(key).getValue() | getMutipleValues()才能获取请求参数值,因为参数值有可能是一个数组,因此被封装成了parameter类型
使用请求参数对应的getter可以直接获得参数值,另外,在Action中应该尽量使用ActionContext访问ServletAPI
通过接口访问ServletAPI
主要有三个接口:
ServletContextAware、ServletRequestAware、ServletResponseAware,分别对应ServletContext、HttpServletRequest、HttpServletResponse
分别需要实现形如public void setA(A a)的方法,从传入方法的参数中就可以拿到对应实例。
通过ServletActionContext类静态方法访问Servlet API
getPageContext()、getRequest() 、getResponse() 、getServletContext(),分别对应PageContext、HttpServletRequest、HttpServletResponse、ServletContext
使用较通过接口访问方便,且多了一个可访问的PageContext,但这使Action与Servlet产生耦合,各有利弊
————————————————————————————————————————————————
关于struts.xml中packag 的name和namespace属性
name不代表某个包,而是代表一个action模块
namespace命名空间,代表一个处理范围
如”/aaaa”命名空间下的action只处理/aaaa/xxxx.action的请求(通过查找name=”xxxx”的Action处理),根命名空间 “/” 只处理”/xxxx.action”的请求,命名空间只处理一个级别的请求,不论自身有多少级,如:
“/aaaa/bbbb/cccc”只处理”/aaaa/bbbb/cccc/xxxx.action”
所有的请求在所属的命名空间找不到对应的action时跳转到默认空间查找
————————————————————————————————————————————————
动态调用Action方法
通过DMI(Dynamic Method Invocation)处理
在JavaScript脚本直接修改action参数直接指向被调用的方法
通过配置通配符调用
在struts.xml中的<action/>标签行可以指定该Action调用的方法,格式为method=”methodName”,可以调用指定Action类下名为methodName的方法
同一个<action />下可以通过使用 通配符+{N} 定义通用处理规则:
例如:
<action name=”*_Index”class=”……..” method=”{1}”>….</action>
表示该action适用于所有形如xxxx_Index的请求,且调用指定Action类的“xxxx”方法,通配符可扩展到N个,{N}表达式也可以用在result、class参数中
使用动态调用应当遵循类似于异常捕捉的组织方法,name=”*”一般应当放在最后一个action中
————————————————————————————————————————————————
关于处理结果<result>
Action的处理结果<result/>
默认:<result type=”dispatcher”,name=”success”>…</result>
通常简化为<result name=”Name”>…</result>
result支持的结果类型type一共有十个,这里仅记录几个比较常用的
dispatcher: <result type=”dispatcher”>/location</result>
redirect:<result type=”redirect”>/location</result>
redirectAction:<result type=”redirectAction”><paramname=”actionName”>ActionName</param><paramname=”namespace”>NameSpace</param></result>
配置全局结果(以及相关内容——异常捕获):<package>
<!—配置全局处理结果-->
<global-results>
<result name=”Name”>/location</result>
</global-results>
<!—配置全局异常捕获,可以与全局处理结果一起使用,构成异常处理-->
<global-exception-mappings>
<!—exception-mapping标签也可以作action的子标签,对局部action有效-->
<exception-mapping exception=”ExeceptionName” result=”Name”/>
<exception-mappin……/>
<action>…</action>
</package>
————————————————————————————————————————————————
Struts2的输入校验
分为字段校验器配置方式和非字段校验器配置方式,这里使用前者
服务器端校验:
方式一:
建立validator文件,格式为ActionName-validation.xml,ActionName为对应该validator的Action,应该被保存在与该Action相同的路径下
注意,服务器端校验失败将默认返回”input”逻辑视图<validators>
<field name="name1">
<!--必填字符串校验,short-circuit="true"设置为短路校验,
该校验规则检验失败将不再检测该表单域后续校验,
实际意义为失败后只显示一个Message而不是多个-->
<field-validator type="requiredstring" short-circuit="true">
<param name="trim">true</param>
<!--Message将显示在被校验表单域的附近-->
<message>Message1</message>
</field-validator>
<!--正则表达式校验,该模式可以实现大部分校验功能-->
<field-validator type="regex">
<param name="regex"><![CDATA[(正则表达式)]]></param>
<message>Message2</message>
</field-validator>
</field>
<field name="name2">
....
</field>
</validators> -->
方式二:
通过注解校验
对需要校验的Action变量的setter方法进行注解//必填字符串校验
private String username;
@RequiredStringValidator(message="message1")
//正则表达式校验
@RegexFieldValidator(regex="正则表达式",message="message2")
public void setUsername(String username){
this.username = username;
}
方式三:
手动校验,自定义校验规则
实际上大多数的规则都能通过正则表达式校验实现,这里不做记录
客户端校验:
这里是基于Struts2的客户端校验配置,主要通过JavaScript实现
也可以通过在页面嵌入纯JavaScript实现
被校验的表单应该使用sruts2标签生成,表单头应当配置 validate=”true” ,例如:<s:form action="login" validate="true">
<s:textfield name="username" key="user"/>
<s:textfield name="password" key="pwd"/>
<s:submit value="ok"/>
</s:form>
————————————————————————————————————————————————
Struts2控制文件上传/下载
上传部分(基于Jakarta):
JSP表单:
应当使用Struts2的标签库
对应Action://省略package/import
public class Upload extends ActionSupport{
private static final long serialVersionUID = 3482281919022527170L;
private String title;
//一个upload表单域对应三个属性
private File upload;
private String uploadContextType;
private String uploadFileName;
//实际本地保存路径
private String savepath;
//省略一些setter/getter
@Override
public String execute() throws IOException {
FileOutputStream fos = new FileOutputStream(getSavepath()+"\\"+getUploadFileName());
FileInputStream fis = new FileInputStream(getUpload());
byte[] byt = new byte[1024];
int len ;
while((len = fis.read(byt)) != -1) {
fos.write(byt,0,len);
}
fos.close();
fis.close();
return Action.SUCCESS;
}
public void setSavepath(String savepath) {
this.savepath = savepath;
}
public String getSavepath() {
//注意这里的实际保存路径
String temp = ServletActionContext.getServletContext().getRealPath(savepath);
System.out.println(temp);
return temp;
}
}
初始化Action成员变量:
<param name=”savepath”>/upload</param>
上传过滤:
方式一:
手动实现
通过初始化Action成员变量传入允许的contentType,手动重写Action类validate方法实现过滤
方式二:
拦截器实现过滤
通过配置fileUpload拦截器的allowedTypes和maximumSize实现类型和大小过滤,具体代码在后边拦截器部分给出
下载部分:
通过配置result的类型可以实现Struts2控制的下载行为:<action name="downloadAction" class="ryo.struts.download.Download">
<param name="path">/WEB-INF/image/1.jpg</param>
<!--result类型为stream-->
<result type="stream">
<param name="contentType">image/jpg</param>
<param name="inputName">inputStream</param>
<param name="contentDisposition">filename="1.jpg"</param>
<param name="bufferSize">2048</param>
</result>
<result name="login">/WEB-INF/login.jsp</result>
</action>
使用自带权限控制的Action类控制下载:package ryo.struts.download;
import java.io.InputStream;
import java.util.Map;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class Download extends ActionSupport{
private static final long serialVersionUID = -1085631150568157686L;
private String path;
@Override
public String execute() {
Map<String, Object> session = ActionContext.getContext().getSession();
String user = (String)session.get("user");
if(user!=null) {
return Action.SUCCESS;
}
return Action.LOGIN;
}
public InputStream getInputStream() {
return ServletActionContext.getServletContext().getResourceAsStream(path);
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
在welcome页面使用超链接跳转至指定的下载行为:<a href=”${pageContext.request.contextPath}/downloadAction.action}”>down</a>
这个链接将执行downloadAction,超链接格式应该为:<a href=”${pageContext.request.contextPath}/nameSpace/actionName.action}”>text</a>
————————————————————————————————————————————————
Struts2拦截器
配置拦截器:
在struts.xml中可以配置拦截器以及拦截器栈<interceptors>
<!--自定义拦截器-->
<interceptor name="interceptor1" class="ryo.sturts.interceptor.MyInterceptor">
</interceptor>
<!--自定义拦截器栈-->
<interceptor-stack name=...>
<interceptor-ref name="栈中第一个拦截器名"/>
.....
</interceptors>
<action...>
<interceptor-ref name="拦截器名或拦截器栈名">
<param name="参数名">值</param>
</interceptor-ref>
<!--需要显式调用默认拦截器栈,或者将默认拦截器加入到自定义拦截器栈中-->
<interceptor-ref name="defaultStack"/>
</action>
例如,使用自带的文件上传拦截器实现文件上传拦截:失败将返回input逻辑视图
配置默认拦截器:
default-interceptor-ref作为package子标签进行配置,方式大同小异,对该包下所有没有配置拦截器的action有效
自定义拦截器类:
通过实现Interceptor接口或继承AbstractInterceptor开发自定义拦截器 自定义拦截器:package ryo.struts.interceptor;
import java.util.Map;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class MyInterceptor extends AbstractInterceptor{
private static final long serialVersionUID = 6821994655329549436L;
@Override
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext context = ActionContext.getContext();
Map<String, Object> session = context.getSession();
System.out.println((String)session.get("user"));
if(session.get("user") != null) {
return invocation.invoke();
}
return Action.LOGIN;
}
}
struts.xml相关配置
Struts2基本
——————————————————————————————————
Struts2的常量配置方法(常量默认值在struts2-core-版本号.jar下org/apache/struts/default.porperties中可找到)
1、配置struts.xml(常用)
例如在struts.xml中指定资源文件
<struts>
…..
<constant name=”struts.custom.il8n.resources”value=”Name”>
…..
</struts>
2、修改struts.properties
3、配置web.xml
Struts2框架有特定的加载配置常量的顺序,后加载的同名常量将被覆盖,先后顺序struts.xml > struts.properties > web.xml
另外在struts.xml中可以通过<includefile=”fileName.xml”/>导入其他配置文件,这可以使struts.xml不会太庞大杂乱,能对其进行模块管理
————————————————————————————————————————————————
实现Action
Aciton是struts的核心,主要对用户请求进行逻辑处理
Action类不需要继承任何的struts基类或者实现任何接口
对请求而言,Action可以没有对应的实例变量,但需要包含变量名对应的getter/setter
但Action有一个默认的实现类ActionSupport,该类继承了Action、Validateable接口,通过继承ActionSupport会使开发更加规范和简单
同时ActionSupport类也是没有定义处理类(<class=””>)的action默认处理类
————————————————————————————————————————————————
访问ServletAPI
通过ActionContext访问Servlet API
主要通过ActionContext实现,可以通过该类的getContext()静态方法获取实例
通过该类实例可以访问/修改application、session、request范围的属性
这里有一个问题是一般获取表单请求参数(不是request属性)时,getParameters()的返回是一个Map(String,Parameter)类型
使用map.get(key).getValue() | getMutipleValues()才能获取请求参数值,因为参数值有可能是一个数组,因此被封装成了parameter类型
使用请求参数对应的getter可以直接获得参数值,另外,在Action中应该尽量使用ActionContext访问ServletAPI
ActionContext | 类似的ServletAPI |
Object get(Object key) void put(String key,Object value) | Object request.getAttribute(String key) void setAttribute(String key,Object value) |
Map getParameters() | Map request.getParameterMap() |
Object getSession().get(Object key) void setSession(Map session) | Object session.getAttribute(String key) void session.setSession(String key ,Object value) |
Object getApplication().get(Object key) void setApplication(Map application) | Object servletcontext.getAttribute(String key) void servletcontext.setAttribute(String key ,Object value) |
通过接口访问ServletAPI
主要有三个接口:
ServletContextAware、ServletRequestAware、ServletResponseAware,分别对应ServletContext、HttpServletRequest、HttpServletResponse
分别需要实现形如public void setA(A a)的方法,从传入方法的参数中就可以拿到对应实例。
通过ServletActionContext类静态方法访问Servlet API
getPageContext()、getRequest() 、getResponse() 、getServletContext(),分别对应PageContext、HttpServletRequest、HttpServletResponse、ServletContext
使用较通过接口访问方便,且多了一个可访问的PageContext,但这使Action与Servlet产生耦合,各有利弊
————————————————————————————————————————————————
关于struts.xml中packag 的name和namespace属性
name不代表某个包,而是代表一个action模块
namespace命名空间,代表一个处理范围
如”/aaaa”命名空间下的action只处理/aaaa/xxxx.action的请求(通过查找name=”xxxx”的Action处理),根命名空间 “/” 只处理”/xxxx.action”的请求,命名空间只处理一个级别的请求,不论自身有多少级,如:
“/aaaa/bbbb/cccc”只处理”/aaaa/bbbb/cccc/xxxx.action”
所有的请求在所属的命名空间找不到对应的action时跳转到默认空间查找
————————————————————————————————————————————————
动态调用Action方法
通过DMI(Dynamic Method Invocation)处理
在JavaScript脚本直接修改action参数直接指向被调用的方法
function login(){ //获取页面首个表单 form0 = document.forms[0]; //修改该表达的action参数 //指向了名为login 动作下的register方法 form0.action = "login!register"; }
通过配置通配符调用
在struts.xml中的<action/>标签行可以指定该Action调用的方法,格式为method=”methodName”,可以调用指定Action类下名为methodName的方法
同一个<action />下可以通过使用 通配符+{N} 定义通用处理规则:
例如:
<action name=”*_Index”class=”……..” method=”{1}”>….</action>
表示该action适用于所有形如xxxx_Index的请求,且调用指定Action类的“xxxx”方法,通配符可扩展到N个,{N}表达式也可以用在result、class参数中
使用动态调用应当遵循类似于异常捕捉的组织方法,name=”*”一般应当放在最后一个action中
————————————————————————————————————————————————
关于处理结果<result>
Action的处理结果<result/>
默认:<result type=”dispatcher”,name=”success”>…</result>
通常简化为<result name=”Name”>…</result>
result支持的结果类型type一共有十个,这里仅记录几个比较常用的
dispatcher: <result type=”dispatcher”>/location</result>
redirect:<result type=”redirect”>/location</result>
redirectAction:<result type=”redirectAction”><paramname=”actionName”>ActionName</param><paramname=”namespace”>NameSpace</param></result>
配置全局结果(以及相关内容——异常捕获):<package>
<!—配置全局处理结果-->
<global-results>
<result name=”Name”>/location</result>
</global-results>
<!—配置全局异常捕获,可以与全局处理结果一起使用,构成异常处理-->
<global-exception-mappings>
<!—exception-mapping标签也可以作action的子标签,对局部action有效-->
<exception-mapping exception=”ExeceptionName” result=”Name”/>
<exception-mappin……/>
<action>…</action>
</package>
————————————————————————————————————————————————
Struts2的输入校验
分为字段校验器配置方式和非字段校验器配置方式,这里使用前者
服务器端校验:
方式一:
建立validator文件,格式为ActionName-validation.xml,ActionName为对应该validator的Action,应该被保存在与该Action相同的路径下
注意,服务器端校验失败将默认返回”input”逻辑视图<validators>
<field name="name1">
<!--必填字符串校验,short-circuit="true"设置为短路校验,
该校验规则检验失败将不再检测该表单域后续校验,
实际意义为失败后只显示一个Message而不是多个-->
<field-validator type="requiredstring" short-circuit="true">
<param name="trim">true</param>
<!--Message将显示在被校验表单域的附近-->
<message>Message1</message>
</field-validator>
<!--正则表达式校验,该模式可以实现大部分校验功能-->
<field-validator type="regex">
<param name="regex"><![CDATA[(正则表达式)]]></param>
<message>Message2</message>
</field-validator>
</field>
<field name="name2">
....
</field>
</validators> -->
方式二:
通过注解校验
对需要校验的Action变量的setter方法进行注解//必填字符串校验
private String username;
@RequiredStringValidator(message="message1")
//正则表达式校验
@RegexFieldValidator(regex="正则表达式",message="message2")
public void setUsername(String username){
this.username = username;
}
方式三:
手动校验,自定义校验规则
实际上大多数的规则都能通过正则表达式校验实现,这里不做记录
客户端校验:
这里是基于Struts2的客户端校验配置,主要通过JavaScript实现
也可以通过在页面嵌入纯JavaScript实现
被校验的表单应该使用sruts2标签生成,表单头应当配置 validate=”true” ,例如:<s:form action="login" validate="true">
<s:textfield name="username" key="user"/>
<s:textfield name="password" key="pwd"/>
<s:submit value="ok"/>
</s:form>
————————————————————————————————————————————————
Struts2控制文件上传/下载
上传部分(基于Jakarta):
JSP表单:
应当使用Struts2的标签库
<s:form action="uploadAction" enctype="multipart/form-data"> <s:textfield name="title" label="filename"/> <s:file name="upload" label="find in file system..."/> <s:submit value="upload"/>
对应Action://省略package/import
public class Upload extends ActionSupport{
private static final long serialVersionUID = 3482281919022527170L;
private String title;
//一个upload表单域对应三个属性
private File upload;
private String uploadContextType;
private String uploadFileName;
//实际本地保存路径
private String savepath;
//省略一些setter/getter
@Override
public String execute() throws IOException {
FileOutputStream fos = new FileOutputStream(getSavepath()+"\\"+getUploadFileName());
FileInputStream fis = new FileInputStream(getUpload());
byte[] byt = new byte[1024];
int len ;
while((len = fis.read(byt)) != -1) {
fos.write(byt,0,len);
}
fos.close();
fis.close();
return Action.SUCCESS;
}
public void setSavepath(String savepath) {
this.savepath = savepath;
}
public String getSavepath() {
//注意这里的实际保存路径
String temp = ServletActionContext.getServletContext().getRealPath(savepath);
System.out.println(temp);
return temp;
}
}
初始化Action成员变量:
<param name=”savepath”>/upload</param>
上传过滤:
方式一:
手动实现
通过初始化Action成员变量传入允许的contentType,手动重写Action类validate方法实现过滤
方式二:
拦截器实现过滤
通过配置fileUpload拦截器的allowedTypes和maximumSize实现类型和大小过滤,具体代码在后边拦截器部分给出
下载部分:
通过配置result的类型可以实现Struts2控制的下载行为:<action name="downloadAction" class="ryo.struts.download.Download">
<param name="path">/WEB-INF/image/1.jpg</param>
<!--result类型为stream-->
<result type="stream">
<param name="contentType">image/jpg</param>
<param name="inputName">inputStream</param>
<param name="contentDisposition">filename="1.jpg"</param>
<param name="bufferSize">2048</param>
</result>
<result name="login">/WEB-INF/login.jsp</result>
</action>
使用自带权限控制的Action类控制下载:package ryo.struts.download;
import java.io.InputStream;
import java.util.Map;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class Download extends ActionSupport{
private static final long serialVersionUID = -1085631150568157686L;
private String path;
@Override
public String execute() {
Map<String, Object> session = ActionContext.getContext().getSession();
String user = (String)session.get("user");
if(user!=null) {
return Action.SUCCESS;
}
return Action.LOGIN;
}
public InputStream getInputStream() {
return ServletActionContext.getServletContext().getResourceAsStream(path);
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
在welcome页面使用超链接跳转至指定的下载行为:<a href=”${pageContext.request.contextPath}/downloadAction.action}”>down</a>
这个链接将执行downloadAction,超链接格式应该为:<a href=”${pageContext.request.contextPath}/nameSpace/actionName.action}”>text</a>
————————————————————————————————————————————————
Struts2拦截器
配置拦截器:
在struts.xml中可以配置拦截器以及拦截器栈<interceptors>
<!--自定义拦截器-->
<interceptor name="interceptor1" class="ryo.sturts.interceptor.MyInterceptor">
</interceptor>
<!--自定义拦截器栈-->
<interceptor-stack name=...>
<interceptor-ref name="栈中第一个拦截器名"/>
.....
</interceptors>
<action...>
<interceptor-ref name="拦截器名或拦截器栈名">
<param name="参数名">值</param>
</interceptor-ref>
<!--需要显式调用默认拦截器栈,或者将默认拦截器加入到自定义拦截器栈中-->
<interceptor-ref name="defaultStack"/>
</action>
例如,使用自带的文件上传拦截器实现文件上传拦截:失败将返回input逻辑视图
<action...> <interceptor-ref name="fileUpload"> <param name="allowedTypes">image/png,image/jpg,image/jpeg</param> <param name="maximumSize">2048</param> </interceptor-ref> <interceptor-ref name="defaultStack"/> ... ... </action>
配置默认拦截器:
default-interceptor-ref作为package子标签进行配置,方式大同小异,对该包下所有没有配置拦截器的action有效
自定义拦截器类:
通过实现Interceptor接口或继承AbstractInterceptor开发自定义拦截器 自定义拦截器:package ryo.struts.interceptor;
import java.util.Map;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class MyInterceptor extends AbstractInterceptor{
private static final long serialVersionUID = 6821994655329549436L;
@Override
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext context = ActionContext.getContext();
Map<String, Object> session = context.getSession();
System.out.println((String)session.get("user"));
if(session.get("user") != null) {
return invocation.invoke();
}
return Action.LOGIN;
}
}
struts.xml相关配置
<interceptors> <interceptor name="authority" class="ryo.sturts.interceptor.MyInterceptor"/> <interceptor-stack name="mystack"> <interceptor-ref name="authority"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors>
<action name="uploadAction" class="ryo.struts.upload.Upload"> <interceptor-ref name="mystack"/> <interceptor-ref name="fileUpload"> <param name="allowedTypes">image/png,image/jpg,image/jpeg</param> <param name="maximumSize">125000</param> </interceptor-ref> <param name="savepath">/upload</param> <result name="success">/WEB-INF/welcome.jsp</result> <result name="input">/WEB-INF/upload.jsp</result> <result name="login">/WEB-INF/login.jsp</result> </action>但我在测试中发现该自定义的权限控制拦截器并没有起效,甚至程序根本就没有跑进该拦截器,但后续的文件上传拦截器却有效这个问题膈应了一整天了,换成Interceptor接口实现的方式也没用,对比了网上很多的demo以及手上的资料还是没能发现哪里不对…
相关文章推荐
- struts2标签的一些基本用法
- zookeeper学习笔记-基本用法进阶
- 关于DSP的一些基本知识和用法(资料来源于合众达网页)
- 读书摘要 C primer plus 指针的基本用法和一些需要清楚的概念(1)
- [转] MongoDB基本介绍及一些用法
- zookeeper学习笔记-基本用法进阶
- c标签和struts2标签一些用法上的区别
- js中正则表达式的一些基本用法
- C# Winform TreeView 的一些基本用法
- UML学习笔记(二):复习面向对象的一些基本概念
- javascript学习笔记(二) js一些基本概念
- 一些基本概念的笔记(技术向)
- 细谈struts2(十一)OGNL表达式的基本语法和用法
- 电商项目笔记之一:复杂一些的struts2配置(自定义拦截器)
- 这是Yii CDbCriteria的一些笔记和常用用法
- Java程序员从笨鸟到菜鸟之(四十九)细谈struts2(十一)OGNL表达式的基本语法和用法
- 黑马程序员学习笔记——Properties类的一些用法
- Lamamda和Linq的一些基本用法
- fmdb的一些基本的用法
- 关于struts2的一些笔记