1、02__Struts2_Struts2_HelloWorld_2.avi
指定Tomcat的目录,指定JDK搭建开发环境(拷贝jar包,复制struts.xml文件 此文件不要放在WEB-INF下面,应该放到src下面 ),在web.xml文件中:
<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>
其中<url-pattern>/*</url-pattern> 不要写/*.do 或者 /*.action约定俗成用/*
2、04__Struts2_Struts2_HelloWorld_3.avi
(1)
<!--<constant >:常量的配置 -->
<!--name="struts.devMode" value="true":当前是开发模式,改动配置文件会自动装载 默认是false-->
<!--命名空间 ---> action -->相应的处理类或页面 -->
<constant name="struts.devMode" value="true" />
<package name="default" namespace="/" extends="struts-default">
<action name="hell" class="package + class xxxx">
<result>
/Hello.jsp
</result>
</action>
</package>
(2)struts.xml不自动提示的解决办法: window--perferences-XML catalog---add---key Type="URI" key="*.dtd"
3、09__Struts2_Struts2_HelloWorld_7_2.avi
struts2的执行流程:
当用户在浏览器中敲入要访问的地址的时候,浏览器会将这个请求发送给tomcat然后tomcat判断应该交给那个WebApplication来处理,然后会读取它下面的web.xml配置发现有配置:
<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>因为<url-pattern> 为/* 它会过滤所有的请求然后就交给filter类org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter处理执行调用doFilter()方法,然后再方法中会读取struts-xml文件,根据用户请求的地址找到相应的package、 action、 result、然后将相应的页面返回给浏览器
4、10__Struts2_Struts2_Namespace_命名空间.avi
(1)namespace决定了action的访问路径,默认为"",可以接收所有路径的action
namespace可以写为/,或者/xxx,或者/xxx/yyy,对应的action访问路径为/index.action,
/xxx/index.action,或者/xxx/yyy/index.action
namespace最好也用模块来进行命名
5、11__Struts2_Struts2_Action.avi
(1)struts1 与struts2的一个重要区别:在struts1中进行多次访问的时候用到的是同一个Action对象。而struts2则是每一次访问都会创建一个Action对象,所以struts2不会有线程安全问题的发生
(2)<result>标签如果没有指定name属性默认返回值为success
(3)<action>标签中的class值如果没有配置相应的类,它会调用struts默认的一个处理类的execute()方法.
(4)实现struts的处理类的时候不要自己随便写类然后定义execute()方法,也不要实现Action类而要从ActionSupport类继承,可以直接使用它为我们定义好的方法.
6、12__Struts2_Struts2_Path_路径问题.avi
(1)struts2中的路径问题是根据action的路径而不是jsp路径来确定,所以尽量不要使用相对路径。
虽然可以用redirect方式解决,但redirect方式并非必要。
解决办法非常简单,统一使用绝对路径。(在jsp中用request.getContextRoot方式来拿到webapp的路径)
或者使用myeclipse经常用的,指定basePath
(2)request.getContextPath()得到项目的名字,一般用来解决路径问题 如果项目为根目录,则得到一个"",即空的字条串。
request.getscheme()返回的协议名称.默认是http
request.getServerName()就是获取你的网站的域名,如果是在本地的话就是localhost
request.getServerPort()获取服务的端口号
7、13__Struts2_Struts2_ActionMethod_DMI_动态方法调用.avi
Action执行的时候并不一定要执行execute方法<br />
可以在配置文件中配置Action的时候用method=来指定执行哪个方法
也可以在url地址中动态指定(动态方法调用DMI)(推荐)<br />
<a href="<%=context %>/user/userAdd">添加用户</a>
<br />
<a href="<%=context %>/user/user!add">添加用户</a>
<br />
前者会产生太多的action,所以不推荐使用
配置文件:
<package name="user" extends="struts-default" namespace="/user">
<action name="userAdd" class="com.bjsxt.struts2.user.action.UserAction" method="add">
<result>/user_add_success.jsp</result>
</action>
<action name="user" class="com.bjsxt.struts2.user.action.UserAction">
<result>/user_add_success.jsp</result>
</action>
</package>
8、14__Struts2_Struts2_ActionWildcard_通配符配置.avi
主要学习通配符的使用 通配符可以将配置量降到最低,不过一定要遵守"约定优于配置"的原则
<package name="actions" extends="struts-default" namespace="/actions">
<action name="Student_add"></action>
<action name="Student_*" class="com.bjsxt.struts2.action.StudentAction" method="{1}">
<result>/Student_{1}_success.jsp</result>
</action>
<!-- 更简便的配置法 -->
<action name="*_*" class="com.bjsxt.struts2.action.{1}Action" method="{2}">
<result>/{1}_{2}_success.jsp</result>
</action>
</package>
说明:
(1){1}代表name="Student*"后面第一个'*',同理{2}代表第二个'*'
(2).如果action之间有重复配置,struts2会匹配最精确的action。如果通配符配置之间有重复,则看前后配置顺序
9、 15__Struts2_Struts2_用Action的属性接收参数.avi
在继承ActionSupport的类中定义要接受的参数,参数的名称与Action所传的名称无关在struts2内部调用的是属性的set方法,所以setxxx()的名字一定要与Action后面所传的值是一样的。
10、16__Struts2_Struts2_用DomainModel接收参数.avi
如果要接受的参数的个数很多,我们可以不用定义属性而是直接定义一个对象例如:
private User user (set get 方法)在调用Action传值的时候使用user!add?user.name=x&user.age=x的方式进行值得传递。(最常用的方式)
11、17__Struts2_Struts2_用ModelDriven接收参数.avi
继承ActionSupport类的处理类必须同时实现ModelDriven<Object>(实现getModel())在传值的时候使用user/user!add?name=bbb进入处理类的时候会调用getModel()方法返回User对象并且把传过来的值set到里面,注意:此时private User user = new User() 不能只定义,要同时实现这样getModel()才能拿到user对象。
12、18__Struts2_Struts2_2.1.6版本的中文问题.avi
在配置文件中加入:
<constant name="struts.i18n.encoding" value="GBK"/> 按照文档说明加入此句可解决中文乱码但是不行这是2.1.6的一个bug,会在下一个版本中修复 如何解决呢:在web.xml中:
<filter-name>struts2</filter-name>
<!--<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>-->
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
把过滤器的版本改成老版本的即可解决该问题!
13、19__Struts2_简单数据验证_1.avi
使用addFieldError方法和s:fieldError标签简单处理数据校验
public String add() {
if(name == null || !name.equals("admin")) {
this.addFieldError("name", "name is error");
this.addFieldError("name", "name is too long");
return ERROR;
}
return SUCCESS;
}
在页面中显示错误信息:
<!-- 以固定的css样式取出错误信息,不方便我们进行相应的处理-->
<s:fielderrorfieldName="name" theme="simple"/>
<!-- 从存储错误信息的Map中拿数据 -->
<s:property value="errors.name[1]"/>
<!-- 显示详细的栈信息-->
<s:debug></s:debug>
14、21__Struts2_访问Web元素_1.avi
注意:web.xml中关于struts的配置一定要采用2.1的,2.0的会取不到这是一个bug
(1)通过ActionContext对象取得Map类型的request, session, application HttpServletRequest, HttpSerletSessionServletContetext:
public class LoginAction1 extends ActionSupport {
private Map request;
private Map session;
private Map application;
//访问此方法,取得相应的对象但是是Map类型
public LoginAction1() {
request = (Map)ActionContext.getContext().get("request");
session = ActionContext.getContext().getSession();
application = ActionContext.getContext().getApplication();
}
//在Map类型的对象中存入相应的值
public String execute() {
request.put("r1", "r1");
session.put("s1", "s1");
application.put("a1", "a1");
return SUCCESS;
}
}
//在页面中通过标签取得存入的数据 二种方法(通过标签, 通过原始方式):
<s:property value="#request.r1"/> | <%=request.getAttribute("r1") %><br />
<s:property value="#session.s1"/> | <%=session.getAttribute("s1") %><br />
<s:property value="#application.a1"/> | <%=application.getAttribute("a1") %><br />
<s:property value="#attr.a1"/><br />
<s:property value="#attr.s1"/><br />
<s:property value="#attr.r1"/><br />
<s:debug></s:debug>
<br />
我们存入Map中的数据居然可以在request,等对象中得到,那么在struts内部他是将Map中的数据全部复制到了request,session等对象中的 #attr ,可以取得所有的属性,但是不推荐使用,为了防止同名的情况,造成无法区别。
(2)通过实现RequestAware,SessionAware, ApplicationAware 接口获取(最常用 和重要的一种)
private Map<String, Object> request;
private Map<String, Object> session;
private Map<String, Object> application;
//DI dependency injection
//IoC inverse of control
public String execute() {
request.put("r1", "r1");
session.put("s1", "s1");
application.put("a1", "a1");
return SUCCESS;
}
@Override
public void setRequest(Map<String, Object> request) {
this.request = request;
}
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
@Override
public void setApplication(Map<String, Object> application) {
this.application = application;
}
(3)通过ServletActionContext()取得真实的相应的对象
privateHttpServletRequest request;
privateHttpSession session;
privateServletContext application;
public LoginAction3() {
request = ServletActionContext.getRequest();
session = request.getSession();
application = session.getServletContext();
}
public String execute() {
request.setAttribute("r1", "r1");
session.setAttribute("s1", "s1");
application.setAttribute("a1", "a1");
return SUCCESS;
}
(4)通过实现ServletRequestAware接口获得相应的对象
privateHttpServletRequest request;
privateHttpSession session;
privateServletContext application;
public String execute() {
request.setAttribute("r1", "r1");
session.setAttribute("s1", "s1");
application.setAttribute("a1", "a1");
return SUCCESS;
}
@Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
this.session = request.getSession();
this.application = session.getServletContext();
}
15、23__Struts2_模块包含
<struts>
<constant name="struts.devMode" value="true" />
<include file="login.xml" />
</struts>
可以将别的写好的配置文件直接包含到struts得配置文件中,方便多人开发避免不必要的配置文件冲突.
login.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="login" extends="struts-default" namespace="/login">
<action name="login*" class="com.bjsxt.struts2.user.action.LoginAction{1}">
<result>/user_login_success.jsp</result>
</action>
</package>
</struts>
16、24__Struts2_默认Action
<package name="default" namespace="/" extends="struts-default">
<!-- 当配置文件中没有用户要访问的Aciton的时候,会调用<default-action-ref 所定义的Action --处理错误页面 -->
<default-action-ref name="index"></default-action-ref>
<action name="index">
<result>/default.jsp</result>
</action>
</package>
17、27__Struts2_结果类型_result_type_1
ResultType的最常用的几种配置:(四种配置分别代表了四种不同的跳转方式)
<package name="resultTypes" namespace="/r" extends="struts-default">
<action name="r1">
<!--type不写默认的为dispatcher:用服务器跳转跳转到结果页面--只能跳转到页面,不能跳转到Action -->
<result type="dispatcher">/r1.jsp</result>
</action>
<action name="r2">
<!--客户端跳转的方式跳转到结果页面 只能跳转到页面,不能跳转到Action -->
<result type="redirect">/r2.jsp</result>
</action>
<action name="r3">
<!--服务器跳转的方式跳转到Action -->
<result type="chain">r1</result>
</action>
<action name="r4">
<!--客户端跳转的方式跳转到Action -->
<result type="redirectAction">r2</result>
</action>
<!--当要跳转的Action在别的包下的时候 应该这样写-->
<action name="r5">
<result type="china">
<parma name="actionName">dashboard</param>
<parma name="namespace">/sesure</param>
</result>
</action>
18、30__Struts2_Global_Results_全局结果集
<package name="user" namespace="/user" extends="struts-default">
<!-- 配置全局的结果集:当返回的result没有配置的时候会执行全局结果集的配置-->
<global-results>
<result name="mainpage">/main.jsp</result>
</global-results>
<action name="index">
<result>/index.jsp</result>
</action>
</package>
<!--关键字extends的使用:我想在下面的这个配置包中使用上面那个包中的结果集,那么可以使用extends关键字继承上一个包
<package name="admin" namespace="/admin" extends="user">
<action name="admin" class="com.bjsxt.struts2.user.action.AdminAction">
<result>/admin.jsp</result>
</action>
</package>
17、31__Struts2_动态结果集_dynamic_result
可以在strtus.xml文件中动态的指定返回的结果集。
public class UserAction extends ActionSupport {
privateint type;
private String r;
public String getR() {
return r;
}
public void setR(String r) {
this.r = r;
}
publicintgetType() {
return type;
}
public void setType(int type) {
this.type = type;
}
@Override
public String execute() throws Exception {
if(type == 1) r="/user_success.jsp";
else if (type == 2) r="/user_error.jsp";
return "success";
}
}
struts.xml文件中的配置:
<package name="user" namespace="/user" extends="struts-default">
<action name="user" class="com.bjsxt.struts2.user.action.UserAction">
<!--可以用${属性名}的方式取得Action中的属性,在服务器端判断好相应的跳转路径然后存到变量里 然后再struts.xml文件中用这种方式取出来,可以极大的增加配置文件的灵活性 -->
<result>${r}</result>
</action>
</package>
18、32__Struts2_带参数的结果集
访问链接格式:<a href="user/user?type=1">传参数</a>
public class UserAction extends ActionSupport {
privateint type;
publicintgetType() {
return type;
}
public void setType(int type) {
this.type = type;
}
@Override
public String execute() throws Exception {
return "success";
}
}
当从一个Action跳转到另一个Action的时候,如果需要传值并且是服务器端的跳转,没有必要再struts.xml文件result的跳转路径中进行传值操作,因为多个服务器端的跳转,共享的是同一个值栈,可以直接取到,但是如果是客户端的跳转(redirect)的方式进行跳转则需要进行如下的配置:
<package name="user" namespace="/user" extends="struts-default">
<action name="user" class="com.bjsxt.struts2.user.action.UserAction">
<!-- 用${}的方式是从值栈取值,注意:不是El表达式 -->
<result type="redirect">/user_success.jsp?t=${type}</result>
</action>
</package>
但是如果在jsp页面取出传输的值用<s:property value="t"/>是取不到的,因为这种方式是在值栈里取值而我们跳转道德是一个jsp页面不是一个Action所以值栈为空,但是我们可以在ActionContext中进行取值:<s:property value="#parameters.t"/>
19、36__Struts2_OGNL_1
在访问Actoin向Action进行传值的时候
http:www.xxxxx/ognl.action?username=u&password=p;
private String username(set get 方法)
private String password(set get 方法)
如果用这种方式进行传值,那么在jsp页面中可以用<s:property value="username"/>进行访问值栈中的内容,没有任何问题但是如果:
http:www.xxxxx/ognl.action?username=u&password=p;
private User user;(set get)方法,使用<s:property value="user"/>依然访问不到,因为如果采用dominModel的方式进行传值,必须:http:www.xxxxx/ognl.action?user.username=u&user.password=p;这样 Struts会在Action中帮助我们new一个User对象,然后把值放进去,但是必须要有User空的构造方法。如果依然使用http:www.xxxxx/ognl.action?username=u&password=p;的方式进行传值,那么在Action中必须手动的初始化User对象,Private User user = new User();这样同样可以访问的到。
20、37__Struts2_OGNL_2
Ognl:Object graph Navigation Language(对象图导航语言):首先看一下下面三个类之间的关系:
public class OgnlAsction extends ActionSupport {
private Cat cat;(set get 方法)
public String m() {
return "你好";
}
}
public class Cat {
private Dog friend;(set get 方法)
}
public Dog {
private String name;(set get 方法)
}
在OgnlAction中包含Cat,而在Cat中包含Dog的对象friend,那么现在我想访问OgnlAction的时候,给friend赋值,我们应该这么写:
http:www.xxxx/ognl.action?cat.friend.name=aaa; 用点进行导航,所以叫做"对象图导航语言"。
21、39__Struts2_OGNL_4
已知以下三个类中的属性和方法:
public class OgnlAsction extends ActionSupport {
private Cat cat;(set get 方法)
private String password;(set get 方法)
List<User> users = new ArrayList<User>();(set get 方法)
}
public class Cat {
private Dog friend;(set get 方法)
private String miaomiao() {
return "miaomiao";
}
}
public Dog {
private String name;(set get 方法)
}
public class S {
public static String STR = "STATIC STRING";
public static String s() {
return "static method";
}
}
(1)访问值栈中对象的普通方法:<s:property value="password.length()"/>
(2)访问值栈中对象的普通方法:<s:property value="cat.miaomiao()" />
(3)访问值栈中的Action的普通属性<s:property value="username"/>
(4)访问值栈中对象的普通属性<s:property value="user.age" />
(5)访问值栈中对象的普通属性<s:property value="cat.friend.name" />
(6)访问值栈中Action的普通方法<s:property value="m()" />
<!--要想访问静态方法,必须在struts.xml文件中加入如下配置才可以 -->
<constant name="struts.ognl.allowStaticMethodAccess"value="true"/>
(7)访问静态方法<s:property value="@com.bjsxt.struts2.ognl.S@s()"/>
(8)访问静态属性:<s:property value="@com.bjsxt.struts2.ognl.S@STR"/>
(9)访问Math类的静态方法:<s:property value="@@max(2,3)" />(不常用)
(10)访问普通类的构造方法:<s:property value="new com.bjsxt.struts2.ognl.User()"
(11)访问List:<s:property value="users"/>
(12)访问List中某个元素:<s:property value="users[1]"/>
<!--把users中的每一个元素User取出来,然后取他们的age属性连接成的字符串-->
(13)访问List中元素某个属性的集合:<s:property value="users.{age}"/>
(14)访问List中元素某个属性的集合中的特定值:<s:property value="users.{age}[0]"/> | <s:property value="users[0].age"/>
(15)访问Set:<s:property value="dogs"/>
<!--下面这样访问set中的某个元素是访问不到的,因为set是没有顺序的 -->
(16)访问Set中某个元素:<s:property value="dogs[1]"/>
(17)访问Map:<s:property value="dogMap"/>
(18)访问Map中某个元素:<s:property value="dogMap.dog101"/> | <s:property value="dogMap['dog101']"/> | <s:property value="dogMap[\"dog101\"]"/>
(19)访问Map中所有的key:<s:property value="dogMap.keys"/>
(20)访问Map中所有的value:<s:property value="dogMap.values"/>
<!--在ognl中他会把size方法看成属性,所以可以不加括号,直接访问 -->
(21)访问容器的大小:<s:property value="dogMap.size()"/> | <s:property value="users.size"/>
<!-- ?#指的是过滤:取出users中的每个age==1的元素 [0]是取第一个,不加会全部取出来
(22)投影(过滤):<s:property value="users.{?#this.age==1}[0]"/>
<!-- ^#:开头取出满足条件的开头的那一个 -->
(23)投影:<s:property value="users.{^#this.age>1}.{age}"/>
<!-- $#:开头取出满足条件的结尾的那一个 -->
(24)投影:<s:property value="users.{$#this.age>1}.{age}"/>
<!--判断 -->
(25)投影:<s:property value="users.{$#this.age>1}.{age} == null"/>
(24)投影:<s:property value="users.{$#this.age>1}.{age}"/>
<!-- value="[1]访问值栈中从上到下的第几个元素,而[0]指的是值栈中从开始到结尾的所有的对象,得到的是一个集合" [0].username:访问值栈中所有元素的username属性,如果没有此属性会依次往下找其他的Action(从一个action跳转到另一个action的时候值栈中会有两个action) -->
(25)[]:<s:property value="[0].username"/>
22、44__Struts2_Struts标签_1
(1)property: <s:property value="username"/>
(2)property 取值为字符串: <s:property value="'username'"/>
<!--如果取到admin的值,就是admin的值否则就是default所定义的默认值 -->
(3)property 设定默认值: <s:property value="admin" default="管理员"/>
<!-- value可以直接写html标签,escape默认为true,会原样不变显示出来,false将把html标签转化为浏览器可以识别的标签,显示相应的效果 -->
(4)property 设定HTML: <s:property value="'<hr/>'" escape="false"/>
HelloWorld
a) 打开eclipse
b) 新建项目
c) 选择myeclipse-java enterprise projects-web project
d) 项目名称:struts2_0100_introduction
e) 选择java ee 5.0
1.设定server
a) window – preferences – myeclipse – servers – tomcat – 6.x
b) 选择tomcat home directory
c) 选择enable
d) finish
1.设定jdk环境
a) window – preferences – java – installed jres
b) 如果没有对应的JDK(不是JRE),选择add
c) 选择standard VM -> next
d) 选择JDK对应的Directory
e) 将刚刚设定的JDK设为默认
1.建立第一个struts2.1的程序
a) 找到struts目录下对应的apps目录
b) 解压struts2-blank-2.1.6.war
c) Copy对应的lib的jar文件,需要除junit和spring-test之外的所有文件,其中commons-io的jar包会在文件上传和下载时需要,其他为必须
d) Copy对应的struts.xml到src目录,在package explorer视图进行操作
e) 注释掉struts.xml的多余内容
f) 建立HelloStruts2_1.jsp文件
g) *修改jsp文件的默认编码属性window-preferences-web-jspfiles-设为Chinese,National Standard
h) 在struts.xml中照原配置进行对应的配置
i) 修改对应的web.xml,建立struts2的filter(参考struts自带的项目)
1.运行项目
a) 可以首先部署到tomcat上项目
b) 也可以项目右键debug as – myeclipse server app,选择刚刚建立好的server
1.其他
a) 学习建立struts的dev-mode,好处在于我们修改了配置文件的时候能够自动热替换
b) 建立jar文件对应的源码D:/share/tools/struts-2.1.6/src/core/src/main/java,以及xwork对应的源码,以及对应的javadoc location,(更好的方式是建立自己的user-library)
c) 浏览struts的目录
d) 认识eclipse jee的项目部署目录,认识如何修改webapp的context-root,项目copy改名后可能会出现的问题
e) package explorer – 建立jar的源文件和目标关联,navigator – 观察所有的内容
f) 认识Action的后缀名,在struts2默认中,带不带action都可以
常见问题:
1.struts.xml不自动提示
a) window – preferences – 搜索 catalog – add
b) 选择key type为URI
c) key: http://struts.apache.org/dtds/struts-2.0.dtd
d) location: 对应的dtd文件,位于struts-core包中,解压开,指定相应位置,如:D:\share\0750_Struts2.1.6\soft\struts-2.1.6\lib\struts2-core-2.1.6\struts-2.0.dtd
1.导入示例项目
a) 注意JDK的版本,应该是JDK6,否则会出class version的问题
b) 如果总是项目出问题,可以重建项目,单独拷文件
c) 还有一种情况是项目右键,properties – java – compiler 选择6.0
d) 另外,在tomcat配置中也要使用jdk6
1.devMode设为true就会出问题空指针问题
a) tomcat路径带了空格
1.在使用ActionContext.getContext().get(“request”)取不到对象,为null值
a) web.xml不要使用2.0的filter,用新的
1.在action的试验中,遇到一个奇怪的bug
a) 用default-action-ref指定一个action
b) 用*_*映射
c) 在地址栏中访问一个不存在的action,如adfsdfsfs
d) 结果居然会映射到*_*上
e) 如果换成*__*就没问题了
f) 靠,只能认为是bug
g) 下次用*-*,不用*_*
学习方法说明
1.先阅读老师的代码
2.再建立自己的项目进行动手学习
3.实现一个Action的最常用方式:从ActionSupport继承(action的class不指定时,默认为该类)
Action
Struts1中用户访问一个action只创建一次,而struts2在每次访问时都会创建一个action(不存在线程同步)
Path问题:相对地址是根据地址栏中的url来定位,并不是根据jsp文件路径来确定,统一使用绝对路径。(myeclipse中的base标签)
1.DMI动态方法调用 !
访问url:ActionName!Action中的方法;
1.通配符配置 * {1} {2} …
a) *_*
{1}对应第一个*
约定由于配置
1.接收参数的方法(一般用属性或者DomainModel(如user类)来接收)
属性传递:调用action中的set和get方法进行传递参数和接受参数
DomainModel传递:url中使用model.para形式传递参数
ModelDriven传递:getModel()方法,url中不用带model.para
1.简单参数验证addFieldError方法
a) 一般不使用Struts2的UI标签
b) <s:debug></s:debug>显示stackContext(actionContext是一个ThreadLocal对象)
在<s:property/>中value=“#request”访问其中的内容
1.访问Web元素
(Map类型的request,session,application,
真实类型的HttpServletRequest,HttpSession,ServletContext)
a) Map类型
1. i. IoC:实现RequestAware接口
2. ii. 依赖Struts2容器
b) 原始类型
1. i. IoC:实现HttpServletRequestAware接口
2. ii. 依赖Struts2容器
3.包含文件配置
4.默认action处理
5.常用四种类型:一次request只有一个值栈
Result
a) dispatcher(默认):服务器跳转,利用服务器跳转(forward)到页面(jsp等)
b) redirect:客户端跳转(url会改变)
c) chain:服务器端跳转,跳转到一个action
d) redirectAction:客户端跳转
1.全局结果集
a) global-results(包内) | extends(继承其他包的result)
1.动态结果(了解)
a) 在action中保存一个属性变量,存储具体的结果location;在配置文件用${变量}来访问值栈
1.传递参数
a) 客户端跳转才需要传递
b) ${}表达式(不是EL)取action的valuestack;
OGNL object graphic navigation language
1.1. <s:property value=”ognl表达式” /> 访问值栈(value->Object)
2.Object Graph Navigation Language 对象.方法/属性
3.想初始化domain model,可以自己new,也可以传参数值,但这时候需要保持参数为空的构造方法
4.其他参考ognl.jsp [0]:从action栈的栈顶开始的对象集合
<li>访问值栈中的action的普通属性: username = <s:property value="username"/> </li>
<li>访问值栈中对象的普通属性(get set方法):<s:property value="user.age"/> | <s:property value="user['age']"/> | <s:property value="user[\"age\"]"/> | wrong: <%--<s:property value="user[age]"/>--%></li>
<li>访问值栈中对象的普通属性(get set方法): <s:property value="cat.friend.name"/></li>
<li>访问值栈中对象的普通方法:<s:property value="password.length()"/></li>
<li>访问值栈中对象的普通方法:<s:property value="cat.miaomiao()" /></li>
<li>访问值栈中action的普通方法:<s:property value="m()" /></li>
<hr />
<li>访问静态方法:<s:property value="@com.bjsxt.struts2.ognl.S@s()"/></li>
<li>访问静态属性:<s:property value="@com.bjsxt.struts2.ognl.S@STR"/></li>
<li>访问Math类的静态方法:<s:property value="@@max(2,3)" /></li>
<hr />
<li>访问普通类的构造方法:<s:property value="new com.bjsxt.struts2.ognl.User(8)"/></li>
<hr />
<li>访问List:<s:property value="users"/></li>
<li>访问List中某个元素:<s:property value="users[1]"/></li>
<li>访问List中元素某个属性的集合:<s:property value="users.{age}"/></li>
<li>访问List中元素某个属性的集合中的特定值:<s:property value="users.{age}[0]"/> | <s:property value="users[0].age"/></li>
<li>访问Set:<s:property value="dogs"/></li>
<li>访问Set中某个元素:<s:property value="dogs[1]"/></li>
<li>访问Map:<s:property value="dogMap"/></li>
<li>访问Map中某个元素:<s:property value="dogMap.dog101"/> | <s:property value="dogMap['dog101']"/> | <s:property value="dogMap[\"dog101\"]"/></li>
<li>访问Map中所有的key:<s:property value="dogMap.keys"/></li>
<li>访问Map中所有的value:<s:property value="dogMap.values"/></li>
<li>访问容器的大小:<s:property value="dogMap.size()"/> | <s:property value="users.size"/> </li>
<hr />
<li>投影(过滤):<s:property value="users.{?#this.age==1}[0]"/></li>
<li>投影:<s:property value="users.{^#this.age>1}.{age}"/></li>
<li>投影:<s:property value="users.{$#this.age>1}.{age}"/></li>
<li>投影:<s:property value="users.{$#this.age>1}.{age} == null"/></li>
<hr />
<li>[]:<s:property value="[0].username"/></li>
1.5. 什么时候在stack中会有两个Action?chain
2.通用标签:
Struts-Tags
a) property
b) set 设置变量,放到actioncontext中
1. i. 默认为action scope,会将值放入request和ActionContext中
2. ii. page、request、session、application
c) bean
d) include(对中文文件支持有问题,不建议使用,如需包含,改用jsp包含)
e) param
f) debug
1.控制标签
a) if elseif else
b) iterator
1. i. collections map enumeration iterator array
c) subset
1.UI标签
a) theme
1. i. simple xhtml(默认) css_xhtml ajax
2.AJAX标签
a) 补充
1.$ # %的区别
a) $用于i18n和struts配置文件
b) #取得ActionContext的值
c) %将原本的文本属性解析为ognl,对于本来就是ognl的属性不起作用
1. i. 参考<s:property 和 <s:include
2.css(覆盖struts2原来的css)
3.覆盖单个文件
4.定义自己的theme
5.实战:freemarker语言
定义自己的theme
a) 把所有主题定义为simple
b) fielderror特殊处理
c) 自己控制其他标签的展现
作业
1.读doc文档:struts-tags
2.设计约定(编码规定)
a) 原则:简单就是美
b) 库名:项目名
c) 表的命名:_Model名
d) 字段:保持和属性名一致(尽量不要起名和数据库命名冲突)
e) 用层来划分包com.bjsxt.bbs.action model(bean) service dto(vo)
f) Action XXXXAction
g) *-* struts2配置文件、jsp命名规则
h) / namespace命名
i) /admin
j) package “action” adminAction
项目开发顺序-以BBS2009的名义
1.建立界面原型
2.建立Struts.xml
a) 确定namespace
b) 确定package
c) 确定Action的名称,空的方法
d) 确定Result
e) 将界面原型页面进行修改,匹配现有设置
f) 测试
g) 做好规划!!!!!
1.建立数据库(或者实体类)
2.建立Model层
3.建立Service层(后面讲了Hibernate后再完善)
a) 此时可以使用JUnit进行单元测试了
1.着手开发
2.在Actoin中进行异常映射 <exception-mapping>
3.在package中进行全局异常映射
4.使用继承共用异常映射
5.Struts2中异常处理由拦截器实现(观察struts-default.xml)
声明式异常处理
a) 实际上Struts2的大多数功能都由拦截器实现
I18N
1.I18N原理
a) ResourceBundle和Locale的概念
b) 资源文件
c) native2ascii
1.Struts的资源文件
a) Action – Package – App级
b) 一般只用APP
1. i. struts.xml custom.i18n
c) PropertiesEditor插件
1. i. 解压
2. ii. features plugin 覆盖到myeclipse中的eclipse目录里
d) 动态语言切换
1. i. request_locale=en_US
2.Struts架构图
Struts拦截器以及源码解析
a) 见文档
1.Struts执行过程分析
2.Interceptor拦截器过程模拟
3.定义自己的拦截器
a) acegi – spring security
1.使用token拦截器控制重复提交(很少用)
2.类型转换
a) 默认转换(url中参数转换为list,set,map等等)
1. i. 日期处理
b) 写自己的转换器:
public class MyPointConverter extends DefaultTypeConverter{
@Override
public Object convertValue(Object value, Class toType) {
if(toType == Point.class) {
Point p = new Point();
String[] strs = (String[])value;
String[] xy = strs[0].split(",");
p.x = Integer.parseInt(xy[0]);
p.y = Integer.parseInt(xy[1]);
return p;
}
if(toType == String.class) {
return value.toString();
}
return super.convertValue(value, toType);
}
}
public class MyPointConverter extends StrutsTypeConverter{
@Override
public Object convertFromString(Map context, String[] values, Class toClass) {
Point p = new Point();
String[] strs = (String[])values;
String[] xy = strs[0].split(",");
p.x = Integer.parseInt(xy[0]);
p.y = Integer.parseInt(xy[1]);
return p;
}
@Override
public String convertToString(Map context, Object o) {
// TODO Auto-generated method stub
return o.toString();
}
}
c) 三种注册方式:
1. i. 局部:XXXAction-conversion.properties
1.p(属性名称) = converter
2. ii. 全局:xwork-conversion.properties
1.com.xxx.XXX(类名)= converter
2. iii. Annotation
d) 如果遇到非常麻烦的映射转换
1. i. request.setAttribute();
2. ii. session
3.Lambda表达式
4.验证框架
5.UI标签
6.类型转换中的异常处理
7.上传与下载文件
8.6. Struts2注解
9.Action
补充视频中讲解的内容
Struts2总结
a) namespace(掌握)
b) path(掌握)
c) DMI(掌握)
d) wildcard(掌握)
e) 接收参数(掌握前两种)
f) 访问request等(掌握Map IOC方式)
g) 简单数据验证(掌握addFieldError和<s:fieldError)
1.Result
a) 结果类型(掌握四种,重点两种)
b) 全局结果(掌握)
c) 动态结果(了解)
1.OGNL表达式(精通)
a) # % $
1.Struts标签
a) 掌握常用的
1.声明式异常处理(了解)
2.I18N(了解)
3.CRUD的过程(最重要是设计与规划)(精通)
4.Interceptor的原理(掌握)
5.类型转换(掌握默认,了解自定义)