缺省参数的配置:
在classes/struts.properties中覆盖,其中如果需要struts支持中文,需要覆写struts.i18n.encoding=GBK;也可以在
struts.xml中使用<constant>来指定。两种方式最好始终只使用一种。
如扩展名struts.action.extension=do
default.properties中配置的项目启动时xml文件加载的顺序:
struts.configuration.files=struts-default.xml,struts-plugin.xml,strurs.xml
struts-fefault.xml中<package name="struts-fefault" abstract="true">的abstract="true"是什么意思?
表示当前的包是抽象包,他要求包中不能有action的配置,在你的子包中加入你自己action的配置,类似于抽象类
团队开发:
struts.xml中的命名空间namespace=""的作用
在package中可以定义namespace,便于团队分模块开发,form提交的时候需要提交到namespaceName/actionName中,
如果在名称空间下面不存在指定的action,则程序会尝试在根目录下去寻找同名的action。
如namespace="admin",JSP表单的action="/admin/login.action",而且必须加上.action,页面上直接访问
http://localhost:8080/test/admin/login.action
struts2中的MVC各是什么
C控制层:web.xml中配置的FilterDispatcher
M业务层:我们的action,实际上是在action调用业务层的,业务层再访问DAO层的
V视力层:
struts.xml的内容分离:
在struts.xml中使用<include file="filename" />来引入子文件,在项目比较大的情况下这种配置文件的部署方式条理比较清晰。 如
<include file="struts_1.xml" />
<include file="struts_2.xml" />
国际化:
message.properties中定义了全局的信息键值对,国际化中支持中文的文件应该命名为message_zh_CN.properties,同时还存在包级别的
message,命名为package_zh_CN.properties,类级别的message,命名为className_zh_CN.properties,优先级别依次递增。
使用这些键值对的方法:
Action中直接使用String getText(String key,String[] param)
validation.xml中<message key="keyname" />
jsp页面中也通过<s:textfield key="keyname" />来指定
模型驱动和属性驱动:
使用页面控件和Action属性直接关联注入的方式是属性驱动,使用纯业务类,并通过Action取得前台输入数据则称之为模型驱动。
模型驱动能提供更好的解耦,在struts中是使用了一个名为modelDrivenFilter的过滤器来实现的,Action需要实现
com.opensymphony.xwork2.ModelDriven<T>接口,覆写getModel()方法并返回一个T类型的实例。不过遗憾的是,这个模型似乎不能和
spring,hibernate等框架很好的结合。
如
public RegisterAction2 extends ActionSupport implements ModelDriven<User>{
private User user=new User();
public User getModel(){
reutrn user;
}
public String execute(){
return SUCCESS;
}
}
com.opensymphony.xwork2.Preparable接口提供了一种在进入Action之前执行业务逻辑的可能性。实现了该接口的Action,会在所有该Action的逻辑方法执行之前执行prepare()方法内的逻辑。
如何让fielderror中的错误信息显示在每一个input的后面??
<s:fielderror cssStyle="color:red"><s:param>name</s:param></s:fielderror>可以指定到底是哪个控件的错误.
如
<td><s:texffield name="username" lable="username" id="usernameId"></s:textfield></td>
<td><s:fielderror cssStyle="color:red"><param>username</s:param></s:fielderror></td>
如何防止表单重复提交?-实际上是tokenInterceptor拦截器进行的处理
做法:
01 在form中增加<s:token></s:token>控件。
02 在action中加入此拦截器
<interceptor-ref name="token"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
如果表单被重复提交,则Action返回一个"invalid.token"的result.如果想要在JSP页面上显重复提交表单的信息,我们在页面上
<s:actionerror cssStyle="color=red"></s:actionerror>,如果想显示中文的错误提示信息,在message_zh_CN.properties中invalid.token=请不要重复提交表单===========================================
struts2与servlet API的三种解耦方法
如果开发过struts1.0的朋友应该知道其与servlet API是耦合的,然而struts2将Action与servlet API进行解耦.它方便了单元测试.struts2提
供了三种方法对servlet API进行解偶.下面就这三种方法讲解一下:
=======================================================================
一:ActionContext,无法获得HttpServletResponse对象
查阅ActionContext的文档,我们发现其有一个public static ActionContext getContext() .
the method returns the ActionContext specific to the current thread. the ActionContext for the current thread, is never null.
这样,我们只需要在execute中用ActionContext接口就能间接地操纵servlet API,所以我们可以在Action中这样操纵servlet:
static ActionContext getContext()获得当前线程的上下文
01 获取session
Map map=ActionContext.getContext().getSession();
map.put("user",user);
02 setAttribute(),getAttribute()方法
ActionContext.getContext() .put(key,value);
ActionContext.getContext() .get(key);
其实这个方法就相当于servlet API中的
HttpServletRequest.setAttribute(key,value);
HttpServletRequest.getAttribute(key);
如
ActionContext.getContext.put("zhangsan","南京大学");
JSP页面上:zhangsan:${requestScope.zhangsan}
03
Map getParameters() 相当于Servlet中的getParameterMap()
struts中访问servlet容器底层内容:
ActionContext类能获取HttpServletRequest对象,进而获得session内容,ServletActionContext类提供了一些静态函数,能获得Request及
Response对象,从而可以设置目标页面的request内容及cookie内容.ServletRequestAware、ServletResponseAware、ServletContextAware接
口可以获取注入的响应容器对象
=======================================================================
第二种方式:ServletActionContext
使用 org.apache.struts2.ServletActionContext类,他继承于 com.opensymphony.xwork2.ActionContext
内部全部为static的方法
static ActionContext getActionContext(HttpServletRequest req)
static PageContext getPageContext()
static HttpServletRequest getRequest()
static HttpServletResponse getResponse()
static ServletContext getServletContext()
static ValueStack getValueStack(HttpServletRequest req)
static void setRequest(HttpServletRequest request)
static void setResponse(HttpServletResponse response)
static void setServletContext(ServletContext servletContext)
----------------------
如HttpServletRequest request= ServletActionServlet.getRequest();
public class LoginAction extends ActionSupport(){
public String execute() throws Exception {
HttpServletResponse response=ServletActionContext.getResponse();
//使用response对象
Cookie cookie = new Cookie("username",this.getUsername());
cookie.setMaxAge(1000);//有效期
response.addCookie(cookie);
return "success";
}
}
=======================================================================
第三种方式:通过action实现相应的接口(最不建议使用)
通过接口使用 --- 典型的依赖注入
-------------------------------------
### ServletContextAware ### 接口
void setServletContext( ServletContext )
### ServletRequestAware ### 接口
void setServletRequest( HttpServletRequest request)
### ServletResponseAware ### 接口
void setServletResponse( HttpServletResponse response)
-------------------------------------
例:
public class LoginAction extends ActionSupport implements ServletRequestAware,ServletResponseAware {
private String username;
private String password;
//setter...getter...
private HttpServletRequest request;
private HttpServletResponse response;
public String execute() throws Exception {
//使用request对象
request.setAttribute("zhangshan","hello");
//使用response对象
Cookie cookie = new Cookie("username",this.getUsername());
cookie.setMaxAge(1000);//有效期
response.addCookie(cookie);
return "success";
}
//这个方法由Strust2框架来自动调用
//调用后,便可以使用容器的request对象了
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public void setServletResponse(HttpServletResponse responset) {
this.response = response;
}
}
---------------------
JSP页面上:zhangsan:${requestScope.zhangsan}
jsp页面中显示cookie
cookie: ${ cookie.username.value}
--------------------
建议:首选ActionConext,其次 ServletActionContext,最后是实现接口XXXXAware(最不建议使用)
动态方法调用:
第一种方法:(建议用此种)
(一个action写多个方法),在struts.xml配置时加上method="xxxx"
第二种方法:
在页面form的action中写ActionName!MethodName.action的话,就会调用相应Action对应类中的名为MethodName的方法,而不调用Execute()方法。 !号前面的是struts.xml中配置的action="name",!号后面的是类中的方法
如<form action="userAction!login.action">
通配符:
在struts.xml中配置Action可以使用通配符
如<Action name="*Login" class="com.test.LoginAction" method="{1}">,{1}对应于*号,则在页面上如果提交到"helloLogin"的话,会执行LoginAction中的hello方法。这种方法看起来比较灵活,一次配置可以解析多个Action,但使用起来容易出错,而且过度使用可能会有多个Action被匹配的情况,需要慎用。
struts2的异常处理机制(全局异常,局部异常)
JAVA中有两种异常
1 运行时异常,也叫未检查异常unchecked
2 非运行时异常,checked,必须捕获
如:
<global-results>
<result name="login" type="redirect">/login.jsp</result>
<result name="passwordInvalid">/passwordInvalid.jsp</result>
</global-results>
<global-exception-mappings>
<global-exception-mapping result="passwordInvalid" exception="com.test.exception.PasswordException"></global-exception-mapping>
</global-exception-mappings>
<action name="login" class="com.test.LoginAction">
<exception-mapping result="usernameInvalid" exception="com.test.exception.UsernameException"></exception-mapping>
<result name="success">/result.jsp</result>
<result name="usernameInvalid">/usernameInvalid.jsp</result>
</action>
action中
public String execute() throws Exception{
//模拟出异常
if(!"hello".equals(this.getUsername)){
throw new UsernameException("用户名错误");
}
else if(!"world".equals(this.getPassword)){
throw new PasswordException("密码错误");
}else{
return SUCCESS;
}
}
com.test.exception
UsernameException.java
public class UsernameException extends Exception{
private String message;//set get
public UsernameException(String message){
supper(message);
this.message=message;
}
}
PasswordException.java
public class PasswordException extends Exception{
private String message;//set get
public PasswordException(String message){
supper(message);
this.message=message;
}
}
页面上:
<s:property value="exception.message" />或者${exception.message}