首页 > 代码库 > struts2学习整理

struts2学习整理

1.struts.xml文件中的<constantname="struts.devMode">中的value改为true,那么以后修改了struts.xml文件的话,它会自动地更新加载,不需要每次修改完都去重启服务器。

2.strurs2的核心控制器是一个Filter,而不是一个servlet,那么在web,xml文件中就需要配置FilterDispather,如

<filter>
<!–配置STRUTS2核心Filter的名字–>
<filter-name>struts</filter-name>
<!–配置STRUTS2核心Filter的名字–>
<filter-class>org.apache.struts2.dispatcher.FilterDispacher</filter-class>

</filter>

<!–置该Filter拦截URL–>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>

</filter-mapping>

3.struts2的运行原理:当在客户端浏览器中输入url地址的话,它的请求通过http协议发送到服务器端(tomcat),tomcat接受到请求之后,判断是哪一个应用程序并找到对应的应用程序,接着会读取相应的web.xml文件中的配置,根据url的输入找到相应类型的<url-pattern>并被它所对应的<filter-class>接受,通过dofilter来看你所输入的namespace(也就是你所访问的路径),它会从struts2.xml文件中查找所对应的namespace,查找之后,再去看是否有对应的同名的action,如有,再去找次action所对应的result,内部是通过forward方式到result所对应的页面的。

4.namespace和我们所访问的路径一一对应,struts2的作用将请求和视图相互分开,更加灵活,

struts.xml文件中的package是用来解决action重名的情况,在action中的result的默认name是success,可以不写,只要在java类中包含返回值为string类型的excute方法,就可以被struts2当作一个action解决,默认情况下action执行的是excute方法。

5.自定义action有3种方式:

1.返回类型为string的excute方法,当读到action是一个带有class时,会去找class对应的对象(每次访问都会new一个新的action),并调用此对应的excute方法,根据excute方法的返回值结果找到对应的jsp页面

默认action是没有class的,它底层默认执行的是ActionSuport对象中的excute方法,并默认返回success

2.实现Action接口,并重写excute方法

3.继承ActionSupprt,并重写excute方法

在实际开发中,会使用第三种方法,因为ActionSupport本身就已经封装了很多方法,可以直接调用此那些方法。

6.struts2和struts1的区别

struts1在访问时,都只有一个action,这样做会有线程安全问题,struts2在每次访问一个action时,会new一个新的action对象(那样就没有线程安全问题)

7.在action中指定method方法,就可以调用该类所对应的方法了,只要这个方法是string类型的,默认是调用excute方法,也可以使用动态调用的方式DMI,如:在struts.xml文件中的action<action name="use" class="..."><result>/used.jsp</result>,而在url中是:http://localhost:8080/myweb/user/use!add。它表示调用名为use的action中所对应class中的add方法

说明:action执行的时,并不一定要执行excute方法,可以在配置文件中的action 中的method来指定要执行的哪个方法,也可以在url地址中用!方式来动态的指定,之所以不推荐使用method方式,因为会产生很多的action

8.在action中指定的method方法就可以调用该类对应的方法了,只要这个方法是string类型的,默认是调用excute方法(这种方式不推荐使用)

可以使用动态方法调用(DMI)如在struts.xml文件中的action中<action name="use" class=".."><result>/user.jsp</result></action>而在url中是:http://localhost:8080/myweb/user/use!add它表示的就是调用名为uszxce的action中所对应的class中的add方法

说明:action执行的时并不一定要执行excute方法,可以在配置文件中的action是用method=来指定需要调用的方法(不推荐),也可以在url地址中用!来动态指定(DMI),之所以不推荐使用method的方式,因为会产生太多的action。

9.通配符,使用通配符将配置降到最低,不过一定要遵守‘约定大约配置’如:struts.xml文件中<action name=‘student*‘ class="..." method="{1}"><result>/studet{1}_success.jsp</result> .

在地址栏中url:http://localhost:8080/myweb/actions/studetadd。

说明:method="{1}"表示的是前面所有通配符中的第一个*,name=“stydent”根据请求的url得到* 对应的是add,所以method={1}表示的是调用所对应的class中所对应的add方法,同理<result>/student{1}_success.jsp</result>就会调用studentadd_success.jsp文件* 是对应你所依赖的url进行配对的。

在一个含有通配符(*)的action中,当一个请求到来,它先找到与之完全匹配的action中的name,如没有就找到最精确匹配的而且谁在前找谁。

10.struts2中接受参数的几种方式

(1)通过action属性获得,当url中有参数传递时如http://localhost:8080/myweb/use!add?name=2&age=2,怎么样获取这些参数呢?

自定义action,在成员变量里设置对应的参数如name,age,并设置相应的set,get方法,那么struts2会自动地将url中的参数值传递到对应的成员变量中去 (底层struts2会自动地将url中的参数值传递到对应的成员方法上,会通过set方式)

(2)通过DomainModel预对象模型进行获得,自定义一个action在成员里面设置一个user的对象,里面有name,age属性和所对应的set,get方法,当在地址上输入ul:http://localhost:8080/localhost/user/use!add?user.name=1&user.age=2,struts2会先通过setuser,再通过setName和setAge进行设值,这样的话就会获得user对象的值了。

11.struts2在进行中文设置的时候,需要在struts.xml文件中constant的name=‘struts.i18n.encoding value=http://www.mamicode.com/gbk‘就可以了。

12.简单数据交验,使用addFieldError方法和s:fieldError标签可以进行简单数据效验如:在一个form中定义一个文本框,名为name(这个是在jsp页面中),而在所对应处理请求的action中定义一个一样的属性name,如if (name=null || name.equals ""){this.addFieldError("name" ,"name is error"); return ERROR;},而在另外一个jsp文件里取得是通过<s:fielderror fieldName="name"/>这样会在页面上显示name is error文字信息,也可以通过<s:property value="http://www.mamicode.com/error.name[0]"/>也可以同样显示这样的信息,可以在jsp页面中用<s:debug></s:debug>标签将所有的actionContext的值和所有的value stack context可以直接通过<s:property>的name取得,说明:s为struts2的标签,需要在jsp文件中引入标签库才可以使用。

13.取得request,session,application的方式有2种,总体是取得map类型的request,session,application,真实类型的HttpServletRequest,HttpSession,servletContext的引用。

(1)依赖于容器,在表单提交的时候,到了后台的action中并定义了map类型的request,session,application即:Map request,session,application=(Map) ActionContext.getContext.get("request");然后再通过方法对这三个属性进行设置(即设置他们的map类型的值)在前台jsp中可以通过request.getAttribute("key")取得相应的值,或是通过<s:property>取值

(2)是IOC(控制反转)它要实现RequestAware,SessionAware,ApplicationAware接口,并重写setRequest,setsession,setApplication的方法,而此时定义的request等仍为反形即 Map<String,Object>request 等而在jsp页面中取得的方式同上面一样(这种方式最常用)

14.模块包含,在struts.xml文件中使用include可以把另外一个xml文件包含近来,相当于复制,好处就是将模块进行分离,相互独立。

默认action<default-action-ref>当别人访问这个namespace时,若找不到对应的action,那么就会默认的用<default-action-ref name="abc">中指定的action的name去访问(这里就会去访问name所对应的action)

15.result类型,包含:dispachter,redirect,chain,redireAction,freemaker,httpheader,stream,velority,xslt,plaintext,toles,其中stream用于下载。

(1)result的type的默认类型是type="dispatcher"这个相当于用于jsp中的forward,用于服务器的跳转到结果页面去(不能挑砖到action中去)用dispather地址栏中显示的是action的name。

(2)redirect是从客户端重定向的跳转,这相当于jsp中的redirect,地址栏中显示的是要访问的那个jsp页面(不可以挑砖到另外一个action中去)

(3)chain可以调转到另外一个action中去,这种是服务器的方式,

redirectAction是用于客户端跳转到另外一个action中去,httpHeader就是一个发送http头消息的。

16.global-results的全局结果机指的是在struts.xml文件中package里面可以共享的结果集如:<global-results><reslut name="mainpage">/main.jsp</result></global-results>表示的是当返回的值就mainpage时,就会挑砖到这个页面

(2)一个包若想使用另外一个package中的内容,要使用<package>中的extends来继承另外一个包,这样就可以使用另外一个包的global了,如<package name="user"><globa-reslut></result name="asd">,若另外一个包象使用这个包的中的global-result可以通过<package name="abv" extends ="user">这样就可以使用那个package了。

17.一次请求只有一个值栈,所以服务器的forward过程中几个action共同使用同一个value stack的值,可以直接访问,当通过redirect或两次请求之间传递参数的时候,可以通过带参数的结果基进行访问,因为redirect或两次请求不是共同用同一个value stack,但是可以从ActionContext中获取值,从其获取的值的时候前面要加上#,如:<s:property value="http://www.mamicode.com/#parameters">.

 18.ognl表达式 :obgect graph naivgation language。指的是操作标签中value里面的表达式,在domain中可以自己new一个对象这个前提是有对应的set/get方法,这样的话就可以使用OGNL表达式了。

(1).访问value stack中的action的普通属性<s:property value="http://www.mamicode.com/name" />

(2).访问值占中对象的普通属性 <s: property value="http://www.mamicode.com/use.age" />这个需要有对应的set/get方法

(3).访问值占中的普通方法<... value="http://www.mamicode.com/password.length()">,<s:property value="http://www.mamicode.com/use.method()">

(4)访问值占中action的普通方法<... value="http://www.mamicode.com/Hello()">

(5).访问值占中的静态方法<s:property value="http://www.mamicode.com/@com.wt.work@add">表示的是要访问work类中的add方法

(6).访问静态属性 <s:property value="http://www.mamicode.com/@com.wt.work@STR">表示要访问work中的STR属性

(7).访问Math类中的静态方法<s:property value="http://www.mamicode.com/@@MAX(1,5)">

(8)访问普通类的构造函数<s:property value="http://www.mamicode.com/new com.wt.work.user(99)">表示要访问user类中带参数的构造函数

(9).访问list,map,set等集合都可以

(10).投影(过滤)只有3个:?#,^#,$#如 :<s:property value="http://www.mamicode.com/user.{?#this.name=1}.{age}">表示name=1时候的那个对象的age。

(11).<s:property value="http://www.mamicode.com/user.{^#this.age>1}.{age}">表示age>1对象中的前一个。

(12).<s:property value="http://www.mamicode.com/user.{$#this.age>1}.{age}">表示age>1对象中的后一个。

(13).[]:<s:property value="http://www.mamicode.com/{0}">表示从ognl的 value stack中从上往下第0个位置开始一直到站底的集合。

19.<s:bean>标签在没有设置var时,对象被放置到value stack的占顶中,当bean标签结束时,就从占顶取走。<s:bean>标签如果 设置了var时,对象就会放到ActionContext中去。

20.struts2通用标签:property,set,bean,include,param,debug.其中set标签默认为action访问,会将值放入到request和ActionContext中,它的范围是:page,request,session,application.控制标签:if ,elseif,else,iterator,subset.

21.在数据库中一般建议使用preparedStatement而不直接使用statement是因为preparedStatement的效率高,在一次编译之后就可以直接从缓冲中获取了,第二是因为可以防止sql注入,安全性好。

22.struts2的声明式异常,(1)当将异常定义在具体某个action时,那么可以在<action>里面定义<exception-mapping result="error" exception="java.sql.exception">那么当在servlet层出现sql异常它就会抛给对应的action,然后再由action查到struts.xml文件中,找到对应的action,再调用对应的页面显示。

(2)对于大多数异常的处理方式:<global-results>和<global-exception-mapping>如:<global-results><result name="error">/error.jsp</result></global-results><global-exception-mapping><exception-mapping result="error" exception="java.lang.Exception"></global-exception-mapping>

注意,<global-exception-mapping>要在<global-results>之后。

在action中进行异常隐射时就想上面的1,在package中进行全局异常映射如上面的2,使用继承同用异常映射。

22.I18N(国际化)的原理:通过一个ResourceBundle类的getBundle方法中,指定你的资源名的前缀如:app同时指定需要加载的资源文件,如有两个资源文件:app_zh_CN.properties和app_en_us.properties,那么再ResourceBundle中 ResourceBundle res=ResoueceBundle.getBundle("app",Locale.US),那么它会自动的加载app_en_us.properties文件,当加载zh_cn的时会出现乱码,那么可以通过native2aseii在dos下将中文转为ascii就可以实现了。

23.i18n有3个级别:Action,package,application

(1)在Action中,哪个资源文件的前缀名要与Action中的类名一样,它表示的应用范围就是这个Action,要和Action放在一个目录下面

(2)在package时,哪个资源文件的前缀名要与package名要一致,表示应用范围在这个包中所有的文件

(3)在Application整个应用程序中,必须将资源文件放在src目录下面,这个前缀名没有要求,在struts.xml文件中 constant 中name="struts.constant.i18n.resources" value="http://www.mamicode.com/是你的前缀名"

24.i18n要传递参数时,先在properties文件中用{0}占位符。如welecome=w{0},然后在前端页面中用<s:text name="welecome"><s:param name="1个ognl‘表达式">这里是字符串</s:param></s:text>.

动态语言切换i18n,如果转换为英语就是在URL地址栏中加上?resquest_locale=en_us即可,中文也是一样。

25.拦截器:一个请求到来时,先在filter中操作一个action,它先操作拦截器,然后再让拦截器去操作action,再返回给拦截器,然后拦截器再返回给filter,再请求中默认都进行了一系列的拦截操作。

自定义拦截器:实现iterceptor接口,并重写itercept方法,同时在struts.xml文件中定义<interceptor><interceptor name="my" class="..."></...>在action中用<interceptor-ref name="my">同时还要用默认的<interceptor-ref name="defaultStack">

26.token拦截器防止重复提交,在要提交的form表单页面中,定义<s:token>标签,同时在struts.xml文件中定义action可以防止在对应的action中进行重复提交如:<interceptor-ref name="defaultStack"></interceptor-ref><interceptor-ref name="token" /><reslut name="invalid.token">/error.jsp</reslut>

那么在重复提交会到error.jsp文件。

27.token为什么可以防止重复提交。当访问页面时,首先在服务器端session里面生成一个随机数,然后再将这个随机数写入到form里面,当再次提交的时,随机数就会带到服务器中与之前的session中的值是否一样,当提交之后服务器就会将session中的那个随机数清除,当再提交的时候服务器发现session中没有那个值,就不容许 重复提交了。

28.自定义类型转换器。当你想在前台或url通过输入参数在后台可以接受到的话,当不是基本数据类型时,可以自定义一个类继承DefaultTypeCoverter并重写convertvalue方法,同时还要通过注册的方式来告诉struts2去用你自定义的类型转换器,有两种注册方式

(1)局部的是要操作的action在一个目录下且名字必须要与Action名一样:XXXAction-Conversion.properties

(2)全局注册,是放入 src目录下面,且名字为XXwork-Conversion.properties,且在properties文件中写如:p=com.wt.myTypeConveter.

也可用自定义一个类继承strutsTypeConverter进行类型转换。

struts2学习整理