MSB-STRUTS-课堂笔记
A:为什么用struts
Q:
1.建立在MVC模式上,MVC都有涉及,但它主要是提供一个好的控制器和一套定制的标签库上,也就是说它的着力点在C和V上,有MVC一系列有点,如:结构层次分明,高可冲永兴,增加了程序的健壮性和可伸缩性,便于开发与设计分工,提供集中校验国际化、日志等等;
2.开源项目,得到了程序大师和高手持续而细心的呵护,并且经受了实战的检验,使其功能越来越强大,体系也日臻完善;
3.其他技术和框架具有良好的融合性。如与spring、hibernate等框架的整合
4.大大提高了开发速度。
A:Framework的概念:
Q:人们用于解决相同或者相似类型问题的方案。
1.特点:可重用性、可扩展性、可收缩性。基于请求响应(request-response)模式的应用Framework的逻辑结构:
控制器(controller)业务逻辑层(business logic)数据逻辑层(data logic)
A:Struts的概念和体系结构
Q:
1.struts是Apache组织的一个开源项目,主要是采用servlet和jsp技术来实现的。
2.struts是一个基于sun java ee平台的mvc框架,它采用mvc模式,将mvc模式“分离显示逻辑和业务逻辑”的能力发挥的淋漓尽致。
A:struts的作用
Q:将请求和视图分开
A:some notice
Q:
1.web.xml里面的Filter要写/*
2.action名称一般用小写
3.dtd是xml提示所用的文件
4.namespace决定action的访问路径,默认""
5.package用来解决action重名的问题
6.凡是名为success的result都可以不写name,默认即为success
7.namespace不写时,即为"",只要输入action的名字(例如index),不管有多少层路径,只要名字符合,都可以用(例如xxx/xx/index,xx/x/xx/x/index都可以访问index)。
不写时,当有其他package处理不了的action(namespace不同),即交给到没有写namespace的package去处理。
8.如果copy项目,重命名后,需要在项目右键properties,在弹出的对话框左侧选择web,修改右侧的web Context-root为/重命名后的项目名称,然后重新部署,就可以访问重命名后的项目。
==============================
action:
1.具体视图的返回可以由用户自己定义的action来决定
2.具体的手段是根据返回的字符串找到对应的配置项,来决定视图的美容
3.具体action的实现可以是一个普通的java类,里面有public String execute方法即可,或者实现action接口,不过最常用的是继承ActionSupport,好处在于可以直接使用struts2封装好的方法。
==============================
自定义action的三种方法:1.继承ActionSupport(推荐),2实现action接口,重写execute(@Override)3写public String execute()方法。
-----------------------------
public class indexAction1{
public String execute(){
return "success";
}
}
-------------------------------
public class indexAction2 implements Action{
@Override
public String execute(){
return "success";
}
}
-------------------------------
推荐
public class indexAction2 extends ActionSupport{
@Override
public String execute(){
return "success";
}
}
--------------------------------
因为:
ActionSupport已经封装了一系列可以直接调用的特别方便的方法。包括validate、input....
实现Action,用不了方法
第一种忘记写execute,就没办法调用了。
============================
如果一个普通类里有execute方法并且返回值为String类型,就可以被struts看做是一个action
==============================
A:struts1和struts2对actin创建方式的不同
Q:
1.struts2是每次访问,必定new一个action对象
struts1每次访问,很有可能用的是同一个
2.Struts1 Action 是单例的模式并且必须是线程安全的,因为仅有 Action 的一个实例来处理所有的请求.单例的策略限制了Struts1 Action 能做的事情,并且要在开发的时候特别的小心. Action 资源必须是线程安全或者同步的
Struts2 Action 对象为每一个请求产生一个实例,因此没有线程安全的问题
A:如果action没有些class将会执行什么?
Q:默认执行ActionSupport的execute方法,只返回success。
==========================================
路径问题说明:
直接访问项目路径,会直接到web.xml,到对应的struts的filter,然后会找对应的namespace,如果没有的话,会返回到web.xml里交给tomcat去处理,会去web.xml里面找<welcome-file-list>下的<welcome-file>节点,访问里面的页面。
A:struts2中的路径问题是根据action的路径而不是jsp路径来确定,所以尽量不要用相对路径。虽然可以用redirect方式解决,单redirect方式并非必要(redirect没用)。
Q:同意使用绝对路径(在jsp中用request.getContextRoot方式来拿到webapp的路径)或者使用myeclipse经常用的,指定basePath。
如果在jsp的head里加<base href="<%=basePath%>"/>以后,页面上所有链接地方则不用写绝对路径,默认采用basePath再追加连接本身的路径。
================================
2014.8.21周四 13
Action执行的时候并不一定要执行execute方法
可以在配置文件中配置action的时候用method=来指定执行哪些方法(因为会产生太多action,所以不推荐使用),也可以用url地址中动态指定(动态方法调用DMI)(推荐)例子:userAction!add
================================
通配符匹配:调用StudentAddAction。 配置里面写的action那么为‘Student*’当没有匹配的action时,则会调用通配符action。method ={1}配置为,如果action的name有八个星号,则会排个顺序,1代表第一个星号。
例子:调用studentAdd。 配置action名字为student*,method{1}。Add则为method名字。ps:也可以配置result,例子: <result>/studnet{1}_success.jsp。 一定要遵守“约定优于配置”。例如都是add,delete
<action name="*_*" class="com.xx.Strtus2.action.{1}Action" method={2}>
<result>/{1}_{2}_success.jsp</result>
</action>PS:大小写一定要相同!!!
注:如果有两个action都可以匹配,则取最精确的为准。
例:Student_add、和 *_*
如果有俩星和仨星的都可以匹配,则按先后顺序取。只要包括星号都属于同一等级。
===============================
用属性接收参数的时候,如果action里面有name字段和age字段。则页面传值时
应调用的是修改字段值得set方法,而不是直接修改属性。所以,字段名改了没关系,但是set方法后面的值,一定要和页面传来的值一样!
==================
使用域模型,提取字段属性和getter、setter方法。在调用实体的action里生命一个私有变量,private 类型 名字; 写对象的get和set方法。
vo:value object
do:data object
dto:data transfer object
==========================
20140824
域模型:不要去在action里面new对象,因为struts2会自动new。
中文问题:有中文就不要用get,全用post。
<form action=user/user!add" method="post">
i18n==internationalization 正好18个字母,所以叫i18n,国际化
struts2.1.6,如果在常亮里设置了i18n编码为gbk后,中文是乱码,这是2.1.6.的bug。2.1.7则会修复此bug。
如果在2.1.6.情况下,在struts的filter之前配置一个filter,解决中文问题。或者把struts的filter改为2.0配置的filterDispatcher。 如果之后学习了spring,则可以用spring的filter解决此问题.
<s:property>专门取valueStack和context里面的值。按照值栈的名字就可以取到对应的值栈的值。
<s:debug>可以显示出value stack context的信息。
struts会把所有属性放在struts valueStack里面去,之后用<s:property>标签取出属性值。
struts会帮我们把action的属性放在值栈里面去,我们取属性的时候就直接用<s:property>标签。
值栈内容里面的property name实际上是一个map,例子:用<s:property value="error"/>取error得到的是值是{name=[name is error]},里面的name是map的key,后面[]里的内容是value.如果想取map里面的某一个key的内容,则用<s:property value="error.name"/>得到value是[name is error],这个value是数组,如果想取数组的第一项,则用<s:property value="error.name[0]"/>。
像error.name[0]这种表达式叫做ognl表达式。
actionErrors是actin本身出问题的信息。
fieldErrors是表示校验属性时的信息。
两个综合在一起就是errors。
=========================
访问web元素request、session、application:
1.不访问response是因为结果是通过result去返回回去的,所以不用管response的事儿。
2.取得Map类型的request、session、application、真实类型的HttpSerletRequest、HttpSession、ServletContext的引用:
前三者:依赖于容器、IOC(只用这种)
后三者:依赖于容器、IOC
Map request=(Map)ActionContext.getContext.get("request");
===========================
思考题:ActionContext.getContext()是否为单例模式?
答:不是单例,因为每个人的请求是不一样的,每个request里面放的值不一样,如果是单例,只能放一个request,那值就不对了。是Tread Local对象,每个线程的名字和对应的值。在这个线程里面是单例。
笔记:
单例模式:单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
要点:一是单例模式的类只提供私有的构造函数,二是类定义中含有一个该类的静态私有对象,三是该类提供了一个静态的共有的函数用于创建或获取它本身的静态私有对象。
优点:1.实例控制、2灵活性
缺点:1.开销(静态初始化解决此问题)、2可能的开发混淆(必须记住自己不能使用new实例化对象)、3对象生存期(不能解决删除单个对象的问题。在提供内存管理的取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。)
================================
20140825
value stack context里的attr会逐个搜索request、session、application里面的值。不过很少用,因为要很精确的知道你想要的值在哪里,否则遇到重名的问题很难确定究竟获取的是哪一个值。(应该忘掉!)
----------------------
IoC:inverse of control:本来自己控制,结果给别人控制了,就叫控制反转。最早是spring推广出来(不是spring提出来的)
DI:dependency injection:如果没有容器(外界的环境)把这个值注入过来,则拿不到这个值。
request很少用,因为value stack本身就在request里。application很少用,全局可以放在数据库里,也可以自己定义一个类,放在里面就好了。比较常用的是session。
---------默认Action----------
在配置actin的xml里,在package下方配置节点<default-action-ref name="默认action的名字"></default-action-ref>就会访问配置的action。
-----------action总结------------------
1.实现一个action最常用的方式:从ActionSupport继承;
2.DMI动态方法调用
3.通配符配置*{1}{2}
4.接收参数的方法(一般用属性或者DomainModel来接收)
5.简单参数验证addFieldError(一般不使用Struts2的UI标签
6.访问Web元素(1.MAP类型a.Ioc、b依赖struts2。2原始类型a、Ioc,b依赖Struts2)
7.包含文件配置
8.默认actin处理
--------------------常见问题----------------------
1.如果用(Map)ActionContext.getContext.get("request");取不到action,有可能是web.xml里面,配置为struts2.0,必须用struts2.1的配置,这是bug!
------resutl的type属性(dispatch、redirect、chain、redirectAction,freemarker、httpheader、stream、v elocity、xslt、plaintext、tiles)-------------------------
1.如果不配置,则默认为dispatcher,运用服务器跳转,也就是jsp forward到一个页面去,只能跳转到页面,不能是action。
2.redirect:只能跳转到视图
3.chain:forward到一个action
4.redirectAction:客户端跳转到action
/*前四个比较常用,重点是1、2,后几个了解不了解无所谓*/
5.freemarker
6.httpheader:发送一个http的头信息
7.stream:下载(和上传没什么关系)
8.velocity(模板框架,现在已经干不过freemarker了):
9.xslt:和xml相关的修饰
10.plaintext:显示网站源码(不是html),做教学网站可能会用到,其他情况用到的不多
11.tiles:用的很少,把页面分成几块,每块可以重新指定,现在几乎不用。
===========================
2014.9.2
1.global result:假如有许多action,它们都有一个共同的结果,与其在每一个action中配置,不如配置一个全局的result。在package里面,所有的action可以公用一个result。
<global-results>
<result name="mainpage">/main.jsp</result>
</global-results>
2.如果另外一个package想用此包的global-result,就extends继承含有global-result的包。
3.如果一个包含有abstract属性,那此包专门用来继承。
4.interceptor和filter的原理一模一样。
5.动态result(用的并不多,了解就可以):<result>${r}</result>,r为action中的属性,在返回时前设置r值,在配置文件里,读取r值。 $用来在配置文件里读取valueStack里的值的OGNL表达式。
6.一次request只有一个值栈,那么服务器端的forward对于客户端来说就是一次request,所以他们两个公用一个request。
7.如果result类型是redirect,需要传valuestack参数,就需要在result里写
<result type="redirect">/x.jsp?参数名=${参数值对象}
8.用forward时不需要传参数,在用redirect的时候,传参数需要用#parameters.参数名
=============================
result总结:
1、常用四种类型(常用为上面两种,下面两种了解就可以):
a.dispatcher(默认)
b.redirect
c.chain
d.redirectAction
2、全局结果集
global-results,如果想用别的包的全局结果集,就extends那个包
3、动态结果(了解)
在action里保存一个属性,存储具体的结果location,需要用${}(不是el)取值
4、传递参数
a.客户端跳转才需要传递
b.s{}从valuestack取值,不是el
==================================
先看文档,再看gogle,最后问身边人。
==================================
Action
1.实现一个action的最常用的方式:从ActionSupport继承
2.DMI动态方法调用:Action!Method
3.通配符配置*{1}{2}
4.接收参数的方法(一般用属性或者DomainModel来接收)
5.简单参数验证addFieldError,一般不使用Struts2的UI标签
6.访问web元素 a、Map(IoC、依赖struts2);b、原始类型(IoC、依赖struts2)
7.包含文件配置:include
8.默认action处理defaultActionReferents(了解即可)
Result
1.常用四种类型:dispatcher(默认)、redirect、chain、redirectAction
2.全局结果集global-results extends
3.动态结果(了解):在action中保存一个属性,存储具体的结果location
4.传递参数:a、客户端跳转才需要传递;b、s{}表达式(不是el)
=================================
OGNL
1.在OGNL表达式里,传参时,如果没有手动new对象,必须要传对象的属性,框架才会自动构造对象,否则对象为空。
2.domain model一般都要提供默认无参构造方法,因为如果框架自动实例化对象,会调用无参构造方法,如果有8个构造都需要传参,没有无参构造方法,这样的情况下,框架是不会自动实例化对象成功的(框架不知道选择哪个有参构造,不知道这些参数该如何传递)。
=====================================
ognl
Object Graph Navigation Language对象图导航语言
=====================================
struts标签(程序设计正常时,基本不用struts标签)
一.通用标签
1.property
2.set
a.默认为actionscope,会将值放入request和ActionContext中
b.page、request、session、application
3.bean
4.include(对中文支持有问题,不建议使用,如需包含,改用jsp包含)
5.param
6.debug
二.控制标签
1.if elseif else
2.iterator
a.collections map enumeration iterator array
3.subset
三.UI标签
1.theme
a simple xhtml(默认) css xhtmlajax
四.AJAX标签
1.补充
五.$#%的区别
1.$用户i18n和struts配置文件
2.#取得ActionContext的值
3.%将原本的文本属性解struts2析为ognl,对于本来就是ognl的属性不起作用
-------------------------------
重要标签:
1:property、set、bean、param、debug
2.if elseif、iterator
ajax用最原始的即可,
其他了解即可。
-------------------------------
20140924:
一、声明式异常处理
1.在Action中进行异常映射
2.在package中进行全局异常映射
3.使用继承公用异常映射
4.struts2中异常处理由拦截器实现(观察struts-default.xml,实际上struts2的大多数功能都由拦截器实现)
二I18N(国际化大网站)
1.原理:
a.ResourceBundle和Locale的概念
b.资源文件
c.native2ascii
2.struts的资源文件
a.Action-Package-App级
b.PropertiesEditor插件(解压,features plugin覆盖到myeclipse中的eclipse目录里)
---------------------------
包级别的I18N资源文件必须以package_开头(这种方式很少用(太麻烦,设置太多),一般用整个应用级别的I18N,开头随便起,必须放在项目根路径下,然后在struts.xml里配置constant:struts.custome.i18n.resources=资源文件开头名称)
---------------------------
资源文件中的参数,在资源文件里写占位符,例如:welcome.msg=wel:{0}
<s:text name="welcome.msg">
<s:parame value="usernmae"></s:param>
</s:text>
取不到的时候就会显示welcome.msg
---------------------------
动态语言切换
url加参数:?request_locale=en_US,提交过去后,整个网站都是英文。
============================
Struts拦截器以及源码解析
1.struts架构图(见桌面,struts流程)
2.struts执行过程分析
3.Interceptor拦截器过程模拟
4.定义自己的拦截器(很少用,用到就是设计思路不对了,因为大多数的拦截器struts已经设计完了,如果自定义struts的拦截器,就相当于与struts框架绑定在一起了,想切换到别的框架,就完了……)
a.如权限判断,acegi(原名)-spring security(改名后):例如在类方法、或者url里面判断权限
5.使用token拦截器控制重复提交(很少用)
6.日期处理
7.类型转换
a.写自己的拦截器(继承DefaultTypeConverter,重写方法convertValue)
b.三种注册方式
ba.局部:XXXAction-conversion.properties(要和action放在同一包下)
p(属性名)=converter
bb.全局:xwork-conversion.properties
com.xx.xx(类型)=converter
bc.Annotation(@element)
如果遇到非常麻烦的映射转换request.setAttribute();
=====================================
Struts2总结
--------------------------------------
1.Action:namespace(掌握)、path(掌握)、DMI,动态方法调用,action!method(掌握)、wildcard通配符(掌握)、接收参数(掌握前两种action属性和domain model)、访问 request等(掌握MAP IOC方式)、简单数据验证(掌握addFieldError和<s:fieldError>)
--------------------------------------
2.Result:结果类型(redirect,dispatcher掌握四种,重点两种)、全局结果(掌握)、动态结果(了解)
--------------------------------
3.OGNL表达式(精通):#%$
-------------------------------
4.struts标签(掌握常用)
4.声明式异常处理(了解)
5.I18(了解)
6.CRUD的过程(最重要是设计与规划)精通
7.Interceptor的原理(掌握)
8.类型转换(默认掌握,了解自定义)