Struts2是由Apache社区的Struts1和Opensysmphony的Webwork整合而来,Struts负责对http请求的处理,Webwork负责业务逻辑处理。
1.导入13个jar包(在Struts2自带的demo中可以找到最少所需包)
2.需要在web.xml文件中配置StrutsPrepareAndExecuteFilter(ctrl+shif+t查找)
3.创建一个struts.xml文件,它的位置是可以放置在src下。(如果没有联网,需要配置约束,DTD映射类型为URL)
大致流程:
(1) 客户端(Client)向Action发用一个请求(Request)
(2) Container通过web.xml映射请求,并获得控制器(Controller)的名字
(3) 容器(Container)调用控制器(StrutsPrepareAndExecuteFilter)。在Struts2.1以前调用FilterDispatcher,Struts2.1以后调用StrutsPrepareAndExecuteFilter
(4) 控制器(Controller)通过ActionMapper获得Action的信息
(5) 控制器(Controller)调用ActionProxy
(6) ActionProxy读取struts.xml文件获取action和interceptor stack的信息。
(7) ActionProxy把request请求传递给ActionInvocation
(8) ActionInvocation根据配置文件加载相关的所有Interceptor拦截器,通过代理模式调用Action和interceptor
(9) 根据action的配置信息,产生result
(10) Result信息返回给ActionInvocation根据struts.xml中配置的result,决定进行下一步输出
(11) 产生一个HttpServletResponse响应
(12) 产生的响应行为发送给客服端。
详细流程:
1.启动服务器(tomcat),StrutsPrepareAndExecuteFilter的init方法执行将会自动加载配置文件
default.properties 在 struts2-core-2.3.7.jar 中 org.apache.struts2包里面(常量的默认值)
struts-default.xml 在 struts2-core-2.3.7.jar(Bean、273行18个默认拦截器、结果类型 )
struts-plugin.xml 在struts-Xxx-2.3.7.jar(在插件包中存在 ,配置插件信息 ) struts-config-browser-plugin-2.3.7.jar里面有
struts.xml 该文件是web应用默认的struts配置文件 (实际开发中,通常写struts.xml )
struts.properties 该文件是Struts的默认配置文件 (配置常量 )
web.xml 该文件是Web应用的配置文件 (配置常量 )
2.请求经过一系列的过滤器(Filter),StrutsPrepareAndExecuteFilter被调用doFilter方法被执行
HttpServletRequestrequest = (HttpServletRequest) req;
HttpServletResponse response =(HttpServletResponse) res;
prepare.setEncodingAndLocale(request,response);//设置编码格式:默认utf-8,根据
default.properties
prepare.createActionContext(request, response);//创建actionContext
prepare.assignDispatcherToThread();//整个的过程都在当前线程中执行
request =prepare.wrapRequest(request);//对request进行了包装
ActionMapping mapping = prepare.findActionMappin(request, response,true);//询问 ActionMapper来决定这个请求是否需要调用某个Action。如果是.action: dispatcher.serviceAction()
3.createAcitonContext(){
//利用容器创建值栈
ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
//构建值栈的结构,把request,session,application等封装成一些map,再把这些map放入到 大map中
stack.getContext().putAll(dispatcher.createContextMap(request, response,null, servletContext));
//把大map的引用指向了ActionContext中的Map<String,Object> context;
ctx = new ActionContext(stack.getContext());
//把整个actionContext放入到了当前线程中,因为actionContext中有valueStack,所以 valueStack也在当前线程中,
//这样就保证了数据的安全性并且在一个线程范围内可以共享数据
ActionContext.setContext(ctx);
}
说明:
1、创建actionContext对象
2、创建ValueStack(实现类OnglValueStack)
3、把整个的actionContext放入到了ThreadLocal中
4.
serviceAction(){
ValueStack stack = (ValueStack)request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
/**
* 因为在struts2容器中有太多的参数request,response,valueStack,session,application,paramters
所以struts2容器对当前的请求中用到所有的数据封装在了ActionContext中的map中
*/
extraContext.put(ActionContext.VALUE_STACK,valueStackFactory.createValueStack(stack));
String namespace = mapping.getNamespace();
String name = mapping.getName();
String method = mapping.getMethod();
//创建actionProxy
ActionProxy proxy =config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
namespace,name, method, extraContext, true, false);
proxy.execute()方法
prepare.cleanupRequest(request);//把struts2过程中的数据全部清空了
}
5.在createActionProxy中执行了如下的内容:
重点:
执行了DefaultActionInvocation中的init方法
createAction(contextMap)调用ObjectFactory中buildAction 创建了action
stack.push(action); 把action放入到了对象的栈顶
contextMap.put("action", action);把action放入到map中
List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors());
interceptors = interceptorList.iterator();
获取所有的拦截器,并且返回了迭代器的形式
6.DefaultActionInvocation中的invoke方法
1、按照顺序的方式执行所有的拦截器
2、执行action中的方法
3、执行结果集
4、按照倒序的方式执行拦截器
invoke(){
//调用了拦截器
if (interceptors.hasNext()) {
final InterceptorMappinginterceptor = (InterceptorMapping) interceptors.next();
String interceptorMsg ="interceptor: " + interceptor.getName();
UtilTimerStack.push(interceptorMsg);
try {resultCode =interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
}
finally{UtilTimerStack.pop(interceptorMsg);
}
}
resultCode = invokeActionOnly();//执行action
//在执行结果集之前执行PreResultListener
if (preResultListeners != null) {
for (ObjectpreResultListener : preResultListeners) {
PreResultListenerlistener = (PreResultListener) preResultListener;
String _profileKey ="preResultListener: ";
try {UtilTimerStack.push(_profileKey);
listener.beforeResult(this, resultCode);
}
finally{UtilTimerStack.pop(_profileKey);
}
}
}
executeResult();//执行结果集
}
总结:
在执行过滤器filter的过程中
1、创建ActionContext
1、创建actionContext
2、创建值栈
3、把actionContext加入到当前线程中
2、创建actionProxy
执行DefaultActionInvocation的init方法
1、创建action
2、把action放入到栈顶
3、创建所有的拦截器,并且产生拦截器的迭代器
3、执行Proxy的execute方法
proxy.execute()---->invocaction.invoke方法
1、执行所有的拦截器
2、执行当前请求的action
3、执行RreResultListener
4、执行结果集
4、清除数据 在finally中,这样即便出错,也能清除
优点:是一款功能强大,成熟而稳定的开源框架,它良好的实现了业务隔离,数据封装等功能,并具有可扩展性。
缺点:a:核心流程写死,无法动态添加内容
b:所有的错误处理采用try方法,使框架显得臃肿
c:与Ajax结合使用过,没有内置错误码,任何错误需要手动设置
第一个加载的是default.properties文件
位置:struts2-core.jar包 org.apache.struts2包下
作用:主要是声明了struts2框架的常量
示例:struts.i18n.encoding=UTF-8(设置post请求字符编码)
struts.multipart.maxSize=2097152(约束文件上传大小)
struts.devMode = false
第二个加载的是一批配置文件
struts-default.xml
位置:struts2-core.jar
作用:声明了interceptor result bean
示例:result 的type种类
dispatcher :Action 转发给 JSP
chain :Action转发到另一个Action (同一次请求)
redirect : Action重定向到 JSP
redirectAction :Action重定向到另一个Action
stream:下载用的(文件上传和下载时再议)
plainText:以纯文本的形式展现内容
struts-plugin.xml
位置:在strtus2的插件包中
作用:主要用于插件的配置声明
struts.xml
位置:在我们自己的工程中
作用:用于我们自己工程使用struts2框架的配置
第三个加载的是自定义的struts.properties
位置:都是在自己工程的src下
作用:定制常量
第四自定义配置提供
第五加载的是web.xml配置文件
主要是加载struts2框架在web.xml文件中的相关配置.
第六 bean相关配置
package配置
1.name属性 作用:定义一个包的名称,它必须唯一。
2.namespace属性 作用:主要是与action标签的name属性联合使用来确定一个action 的访问路径
3.extends属性 作用:指定继承自哪个包。一般值是struts-default
strtus-default包是在struts-default.xml文件中声明的。
4.abstruct属性 它代表当前包是一个抽象的,主要是用于被继承
action配置
1.name属性 作用:主要是与package的namespace联合使用来确定一个action的访问路 径
2.class属性 作用:用于指示当前的action类
3.method属性 作用:用于指示当前的action类中的哪个方法执行(默认execute,并默认返回success)
result配置
它主要是用于指示结果视图
1.name属性 作用是与action类的method方法的返回值进行匹配,来确定跳转路径
2.type属性 作用是用于指定跳转方式(默认dispatcher)
常量配置
struts.xml (推举)
格式 : <constant name="struts.devMode" value="true"/>
struts.properties(要求)
格式 : struts.devMode = true
web.xml <init-param>
<param-name>struts.devMode</param-name>
<param-value>true</param-value>
</init-param>
*<constantname="struts.i18n.encoding" value="UTF-8"/> 可以帮助我们解决post请求乱码问题
<constant name="struts.action.extension"value="action"/> 指定访问struts2框架路径的扩展名>
<constant name="struts.devMode" value="true">
配置这项后,它会提供更加详细报错信息,以及在struts.xml文件修改后不在需要重启服务器
拦截器配置
在要拦截的action所在的package里面声明拦截器
在要拦截的action里面使用拦截器
如果使用自定义的拦截器,默认的拦截器不会执行的,手动使用默认的拦截器
<package name="demo2" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="pre"class="cn.itcast.demo2.Invacaton"></interceptor>
</interceptors>
<action name="demo2" class="cn.itcast.demo2.DemoAction" >
result>/index.jsp</result>
<result name="login">/demo100.jsp</result>
<interceptor-ref name="pre"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
/package>
*指定拦截方法
我们可以使用Interceptor接口的一个实现类来完成操作
在配置时,就可以指定哪些方法拦截,哪些方法不拦截
*过滤器和拦截器的区别
过滤器:在目标资源之前进行的操作
过滤所有的内容,比如action、servlet、jsp、html
拦截器:在目标资源之前进行的操作
不能拦截所有的内容,拦截action,不能拦截jsp,不能拦截html
拦截器和过滤器之间有很多相同之处,但是两者之间存在根本的差别。其主要区别为以下几点:
1)拦截器是基于JAVA反射机制的,而过滤器是基于函数回调的。
2)拦截器不依赖于Servlet容器,而过滤器依赖于Servlet容器
3)拦截器只能对Action请求起作用,而过滤器可以对几乎所有的请求起作用。
4)拦截器可以访问Action上下文、值栈里的对象,而过滤器不能
5)在Action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
对指定的方法校验
1格式:Action类名-validation.xml 针对动作类中的指定方法进行校验,使用@SkipValidation注解
2格式 : Action类名-ActionName(<action>元素name属性)-validation.xml
<validators>
<validator type=”requiredstring”>
<param name=”fileName”>password</param>
<validator>
</validators>
引入标签库:<%@ taglib uri="/struts-tags" prefix="s"%>
常见标签
格式 作用
<s:propertyvalue=”ognl表达式”/> 获取数据并输入页面
<s:set scope=””var=”” value=””/> 令var=value存入scope中
<s:pushvalue=””/> 将value压入值栈
<s:if><s:elseif><s:else> 等同if(){}elseif(){}else{}
<s:iteratorvar=”” value=””......> 遍历集合或数组、域对象
<s:表单标签> 与HTML标签友好交互
<s:actionerror><s:filederror> 获取错误信息
<s:debug> 查看值栈信息
*addFieldError、addActionError有何区别?
都是com.opensymphony.xwork2.ActionSupport类下的方法.
addActionError (String anErrorMessage)
添加一个Action级别的错误消息到Action
anErrorMessage:错误消息,被存放在List列表中
显示消息的标签是(如放在jsp页面中):
<s:actionerror/> 显示全部的 Action级别的错误消息,可以加CSS代码
addFieldError (String fieldName, String errorMessage)
给一个字段(属性) 添加错误消息
fieldName:字段(属性)名
errorMessage:错误消息,被存放在一个Map<key, value>中(其中key存放的是 fieldName,value存放的是errorMessage)。
显示消息的标签是(如放在jsp页面中):
<s:fielderror/> 显示全部的错误消息(用addFieldError方法添加的 )
1. 创建一个pojo类
Pojo(plani Ordinary java object)简单的java对象
Pojo类就是没有实现任何接口没有继承任何类
优点:无耦合
缺点:所有的功能都要自己完成
2. 创建一个类实现一个Action接口
com.opensymphony.xwork2.Action
在Action接口中定义了五个常量,一个execute方法
五个常量:它们是默认的五个结果视图<result name=””>:
ERROR : 错误视图
INPUT: 它是struts2框架中interceptor中发现问题后会访问的一个视图
LOGIN:它是一个登录视图,可以在权限操作中使用
NONE:它代表的是null,什么都不做(也不会做跳转操作)
SUCCESS:这是一个成功视图
优点:耦合度低
缺点:还是需要自己来完成功能
3.创建一个类继承ActionSupport类(推举)
com.opensymphony.xwork2.ActionSupport
ActionSupport类也实现了Action接口。
主要有两种方式:
1.属性驱动
a.直接在action类中提供与请求参数匹配属性,提供get/set方法
b.在action类中创始一个javaBean,对其提供get/set ,在请求时页面上要进行修改, 例如 user.username user.password ,要使用ognl表达式
以上两种方式的优缺点:
第一种比较简单,在实际操作我们需要将action的属性在赋值给模型(javaBean) 去操作
第二种:不需要在直接将值给javaBean过程,因为直接将数据封装到了javaBean 中。它要求在页面上必须使用ognl表达式,就存在页面不通用问题。
2.模型驱动(推举)
步骤:
1.让Action类要实现一个指定接口ModelDriven
2.实例化模型对象(就是要new出来javaBean)
3.重写getModel方法将实例化的模型返回。
对于模型驱动它与属性驱动对比,在实际开发中使用比较多,模型驱动缺点,它只能对 一个模型数据进行封装。
ServletActionContext获取(推举)
采用注入方式
Struts2框架在运行时,请求会被StrutsPrepareAndExecuteFilter拦截,会根据请求,去 strtus.xml文件中查找到匹配的action,在action执行前,会走一些interceptor
默认执行的拦截器是struts-default.xml文件中定义的。
在默认执行的拦截器中有一个
查看一下ServletConfigInterceptor源代码
以下是部分源代码
ServletRequestAware, 实现这个接口可以获取HttpServletRequest
ServletResponseAware ,实现这个接口可以获取HttpServletResponse
ServletContextAware 实现这个接口可以获取ServletContext
依赖于request请求的一种数据容器,每次request请求都会创建一个action实例,而每一个action实例都对应一个valueStack(它保存在request中,是request的一个属性),valueStack存储action对象以及其他对象内容。
值栈由两部分组成
root:compoundRoot其实就是一个ArrayList.
context :OgnlContext其实就是一个Map。context中有root的引用,request、 session、application、 attr、 parameters等对象引用
* 操作值栈默认指 操作 root 元素
获取值栈
值的存取
ActionContext.getContext().getValueStack().push(Object) ,
将对象注入到栈顶对象栈 JSP页面通过 javabean 属性名获取
ActionContext.getContext().getValueStack().set(k ,v ) ,
把一个对象变成map存入到对象栈中 JSP页面 “key” 获得
ActionContext.getContext().put(k ,v )
把一个数据直接放入到map栈中 , JSP页面“#key”
*如何在JSP页面获取数据
访问root中数据 不需要#
访问 其它对象数据 加 #
通过下标获取root中对象
<s:property value="[0].top"/> //取值栈顶对象
直接在root中查找对象属性 (自上而下自动查找)
valueStack:<s:propertyvalue="username"/>
(1)对象保存到值栈
<s:propertyvalue="user.username"/>
(2) 集合保存到值栈
<s:propertyvalue="list[0].username"/>
在OgnlContext中获取数据
request:<s:propertyvalue="#request.username"/>
session:<s:propertyvalue="#session.username"/>
application:<s:propertyvalue="#application.username"/>
attr:<s:propertyvalue="#attr.username"/>
parameters:<s:propertyvalue="#parameters.cid"/>
struts内置存储过程
每次请求,访问action,这个对象会存储到valueStack中。
在DefaultActionInvocation的init方法内
在ModelDrivernInterceptor中
以上代码会将模型对象存储到valueStack中。
EL表达式取值
由于在struts2中重写了request的getAttribute方法,如果在request域对象中获取不到值就会在valueStack中查找。
#号:它是从非root中获取数据
%用于强制是否要解析ognl表达式
$它主要是从配置文件中来获取valueStack中数据
单文件上传
浏览器端注意事项:
表单提交方式method=post
表单中必须有一个<input type=”file” name=””>组件
表单中必须设置enctype=”multipart/form-data”
服务器端
导入 Commons-fileupoad.jar包
Struts2框架本身支持文件上传
Struts2框架使用一个fileupload的interceptor来完成文件上传,而我们要使用它
在action中我们可以提供类似以下的操作就能完成文件上传操作(必须有对应set方法)
在execute方法中将文件copy就可以完成文件上传。
多文件上传
页面
对象
方法
文件上传时出现了问题
现在的问题是我们的action中没有设置input视图
在页面上可以通过
在default.properties中
struts.multipart.maxSize=2097152 (2m)
它是描述文件上传时允许的最大值
只需要在struts.xml文件中
我们还可以查看FileuploadInterceptor
用HttpServletRuqest处理
在浏览器端
在服务器端
使用自带的json插件
首先要导入插件包:struts2-json-pligin-2.3.24.jar
然后在struts.xml中进行如下操作
1. 将我们自己配置文件中的<packageextends=”json-default”>.
2. Action的返回视图<result name=”” type=”json”>
浏览器端
服务器端
注意:要想使用struts2的注解,我们必须单独在导入一个jar包。
@Namespace来代替<package namespace=””>
@ParentPackage来代替<packageextends=””>
@Action来描述关于<action>配置
value属性<action name=””>
使用@Action的results来描述关于结果类型的配置<result>
<result name=”” type=””>
@Action(value=””,results={@Result(name=””,type=””,location=””)})
@Actions
作用:可以通过多个映射来访问同一个action
@Results 类似于全局的结果视图
@InterceptorRef 它是用于处理拦截器的
问题:我们在action类中定义了注解,strtus2框架怎样识别它们?
原因:我们必须查看插件包中的配置
是在action,actions,struts,struts2这样的包下扫描注解
文章浏览阅读558次。相机参数修改:加速度和角速度发表在两个话题,用上述方法将其发表在一个话题上。修改VINS-MONO包:_vins调参
文章浏览阅读4.8k次,点赞11次,收藏40次。十进制转二进制_c++十进制转二进制
文章浏览阅读1k次。主要适用场景当要更新一条记录的时候,希望这条记录没有被别人更新乐观锁实现方式:取出记录时,获取当前version更新时,带上这个version执行更新时, set version = yourVersion+1 where version = yourVersion如果version不对,就更新失败乐观锁配置需要2步 记得两步1、插件配置spring xml<bean class="com.baomidou.mybatisplus.plugins.OptimisticLocke_mybatis mybatisplus 2.x 最稳定版本
文章浏览阅读5.2k次,点赞9次,收藏55次。python-docx 是用于创建和更新Microsoft Word(.docx)文件的Python库。它的API文档也非常简单,看完之后,只能简单理解一些基础用法。最近碰到一个需求,需要对word模版里的内容进行统一替换,替换内容比较多。从网上查到了很多种基于python-docx 的做法,但都有一定的缺陷,不能适用于各种场景。网上的做法整体是两种:相对比较好的解决办法:对runs中的内容进行一定程度的拼接,但是有缺点,部分文字的样式可能会消失,可以尽量让每一段文字的样式保持一致来避免这种情况。..._def replace_word(doc, tag, pv): # replace in paragraph
文章浏览阅读754次,点赞24次,收藏20次。1.背景介绍无监督学习是一种通过分析数据中的模式和结构来自动发现隐含结构的学习方法。它主要应用于数据竞争中,通过对数据的分类、聚类、降维等方式来提取数据中的知识。高斯混合模型(Gaussian Mixture Model, GMM)是一种常用的无监督学习方法,它假设数据是由多个高斯分布组成的混合分布,并通过估计这些高斯分布的参数来实现数据的聚类。在本文中,我们将详细介绍高斯混合模型在无监督...
文章浏览阅读173次。近年来,国家把科技自立自强作为国家发展的战略支撑,越来越多的行业企业将自主创新、自主研发作为发展的重中之重,以此增强企业的核心竞争实力。在今年发布的政府工作报告中,也对推动科技创新发展提出了众多战略要求。华云数据是中国云计算独角兽,自成立以来,始终坚持以技术创新为根本,坚持自主研发,至今已获得500余项知识产权。已经具备支持多芯多栈的解决方案,在复杂的混合IT架构背景下,可以为用户提供完整的数据中心云化、云上办公、信创转型和公有云方案。随着5G、云计算、大数据等技术的快速发展,以及移动办公、远程协作等._华云数据 体验最好的云桌面
文章浏览阅读1.8k次。简介:材料的结构影响其性能,对半导体材料的结构进行表征,可以通过其电子能带结构解析材料的光电性能,因此对半导体材料的能带结构测试十分关键。本文简述了紫外可见近红外分光光度计(UV-VIS-NIR)的基本原理、仪器结构及其在半导体材料带隙分析中的应用。1. UV-VIS-NIR仪器简介紫外可见近红外分光光度计(UV-VIS-NIR)可覆盖UV-VIS-NIR全波段光谱范围,实现紫外、可..._紫外可见分光光度计uv/vis/nir(积分球)可以测能带结构吗
文章浏览阅读2.1k次。文章目录 第十四章 SQL命令 CREATE TABLE(一)大纲参数描述语法概述SQL安全和权限表名表存在 第十四章 SQL命令 CREATE TABLE(一)创建表大纲CREATE [GLOBAL TEMPORARY] TABLE table (table-element-commalist) [shard-key] [WITH table-option-commalist]table-element ::= [%DESCRIPTION string] [%FILE_create table with 是什么语法
文章浏览阅读1.9k次,点赞2次,收藏4次。Winform检查窗体是否打开_winform判断窗体是否打开
文章浏览阅读1.9w次,点赞6次,收藏18次。解决方式:Win+R,输入services.msc,找到mysql服务即默认的服务名是mysql55而不是mysql直接输入mysql进入数据库报错这是因为系统并不知道mysql是什么,我们需要在环境变量里添加mysql的安装地址中的bin目录地址。C:\Program Files\MySQL\MySQL Server5.5\bin;..._mysql使用cmd语句打开不显示sql命令
文章浏览阅读7.2k次。如题:tensorflow.python.framework.errors_impl.UnknownError: Could not start gRPC server环境:Ubuntu16.4,tensorflow-gpu1.10原因:分布式tensorflow中的ps或者worker进程为杀死解决方案:ps -aux|grep python然后杀死和分布式有关的进程:..._tensorflow.python.framework.errors_impl.unknownerror: could not start grpc s
文章浏览阅读3k次。Python参考手册(第4版)》(David M.Beazley)电子书网盘下载免费在线阅读资源链接:链接: 提取码: kybr 书名:Python参考手册(第4版)作者:David M.Beazley译者:谢俊豆瓣评分:7.4出版社:人民邮电出版社出版年份:2010-12页数:540内容简介:本书是权威的Python语言参考指南,内容涉及核心Python语言和Python库的最重要部分。因此,它作为一个两卷本的合集中的第一本:《Learning Python》,也就是这本书,介绍Python本身。_python官方文档中文版下载