Struts入门Struts 框架响应客户请求的流程 国际化 异常.docx
《Struts入门Struts 框架响应客户请求的流程 国际化 异常.docx》由会员分享,可在线阅读,更多相关《Struts入门Struts 框架响应客户请求的流程 国际化 异常.docx(16页珍藏版)》请在冰豆网上搜索。
![Struts入门Struts 框架响应客户请求的流程 国际化 异常.docx](https://file1.bdocx.com/fileroot1/2023-1/22/4933fa93-f0c6-4098-9e2d-98c0bc8a1243/4933fa93-f0c6-4098-9e2d-98c0bc8a12431.gif)
Struts入门Struts框架响应客户请求的流程国际化异常
Struts入门(Struts框架响应客户请求的流程+国际化+异常)
Struts入门(Struts框架响应客户请求的流程+国际化+异常)
Struts实际上是在JSPModel2上实现的一个MVC的框架。
模型:
如JavaBeanEJB
控制器:
ActionServletAction
视图:
JSPStruts客户化标签
前端控制器:
ActionServlet
控制器:
Action
模型:
ActionFormBean
控制器与模型之间的映射:
ActionMapping
转发:
ActionForward
错误与信息处理:
ActionError
ActionFormBean它也是一种JavaBean,除了一些JavaBean的常规方法,另外它还包含一些特殊的方法用于
验证其中数据的完整性。
Struts利用ActionFormBean来进行View组件与Controller组件之间表单数据的传递。
Struts框架把View组件接受的用户输入的表单数据保存在ActionFormbean之中,把它传递给Controller
组件,Controller组件可以对ActionFormBean中的数据进行修改。
Jsp文件使用Struts标签读取修改后的ActionFormBean的信息,重新设置HTML表单。
对于采用Struts的Web应用,在Web应用启动时会加载并初始化控制器ActionServlet。
ActionServlet从struts-config.xml配置文件中读取配置信息,再把它们存放到ActionMappings对象中。
ActionServlet在接收到用户请求时会检查对应的ActionMapping的实例是否存在,如果不存在则会创建一
个ActionMapping的实例,其中包含了把请求转发至那个Action的信息。
ActionServlet会根据配置文件检查Action对应的ActionForm的实例,如果ActionForm的实例不存在,则
会创建一个ActionForm的对象,并将客户提交的表单数据保存到ActionForm中。
ActionServlet在获取或建立ActionForm后,会根据配置是否需要验证来执行ActionForm的validate()方
法进行验证。
如果ActionForm的validate方法返回一个null或一个不包含ActionMessage的ActionErrors对象,就表示
表单验证成功。
ActionServlet根据配置来确定将请求转发给那个Action,如果相应的Action实例不存在,就会先创建这个
实例,然后调用它的execute方法。
Action的execute方法将返回一个ActionForward对象,ActionServlet再将请求转发给ActionForward中指
向的JSP组件。
然后ActionForward中指向的JSP组件生成动态网页返回给用户。
注:
在执行ActionForm的validate方法进行数据验证时,如果验证失败(即:
返回不为空,为一个
ActionError或ActionErrors对象时),此时ActionServlet会直接将请求转发给包客户提交表单的JSP组
件。
这种情况下,将不再创建Action对象并调用它的execute方法。
在Struts各种组件中最重要的组件就是控制器组件.
Struts控制器组件的组成:
Struts控制器主要由ActionServlet组成,另外包含
RequestProcessorAction及ActionForward三个辅助类.
Struts多应用模块:
多应用模块是指同一个应用包含多个子应用,每个子应用可以处理相关的一组功能,例如:
对于网上购物
,可以由一个子应用来处理商品和商品目录信息.再由另一个子应用来处理购物车和订单信息.
把应用划分为多个模块,可以简化应用的并行开发过程,缩短开发周期.
在Struts中,所有的子应用都共享同一个ServletAction但是每一个子应用都有单独的配置文件和
RequestProcesser实例.
Struts框架的初始化流程:
Servlet容器会在ActionServlet被加载后立即执行它的init()方法,以下是ActionServlet的init的执行
过程分析:
调用initInternal()方法,初始化所有在Struts框架中用到的消息资源,例如:
日志,警告,错误信息等
调用initOther()方法,从web.xml中加载ActionServlet的初始化参数,例如:
config等.
调用initServlet()方法,从web.xml中加载ActionServlet的URL映射信息.
调用initModuleConfig()方法,加载并解析默认子应用模块的Struts配置文件,并创建ModuleConfig对象
,并且将它存储在ServletContext中.
调用initModuleMessageResource()方法,加载并初始化默认子应用模块的消息资源,并且建立
MessageResources对象,并将它保存在ServletContext中.
调用initModuleDataSource()方法,加载并实始化默认的子应用模块数据源,如果没有在struts的配置文
件中配置<data-source>元素,这一步将被忽略.
调用initModulePlugins()方法,加载并初始化默认子应用模块的所有插件.
当默认的子应用模块初始化成功后,如果还有其它的子应用模块,ActionServlet将重复4到7的步骤,分
别对其它子模块进行初始化.
Struts框架响应客户请求的流程:
当ActionServlet实例接收到HTTP请求后,在doGet()和doPost()方法中都会调用process()方法来处理请求.
ModuleUtils.getInstance().selectModule(request,getServletContext());//选择请求相关
的子应用模块
ModuleConfigconfig=getModuleConfig(request);//获取请求相关的配置文件
RequestProcessorprocessor=getProcessorForModule(config);//获取请求相关的处理器
if(processor==null){
processor=getRequestProcessor(config);
}
processor.process(request,response);
RequestProcesser的process()方法:
首先调用processMultipart()方法.如果Http请求的为Post方法,并且请求的Content-type的类型为
mutipart/form-data,标准的HttpServletRequest将被重新封装以处理多数据体的Http请求,如果没有设
定Content-type则直接返回HttpServletRequest对象.
调用processPath()方法,获取请求的URI路径,该信息用于选择合适的Action组件
调用processLocale()方法,当ControllerConfig中的locale属性为true时,将读取用户请求中包含的
locale信息,然后把locale信息保存在session范围内.
调用processContent()方法,读取ControllerConfig中的contentType属性,然后调用
response.setContentType(contentType)的方法设置响应的文档类型及字符编码.
调用processNoCache()方法,通过读取ControllerConfig对象的nocache属性来设置是否在客户端的浏览
器中缓存页面.如果参数为true,那么将在响应的头信息中加入特定的头信息:
Pragma,Cache-Control
和Expries.
调用processPreprocess()方法.该方法用于自定义的RequestProcesser重载,执行客户化的预处理请求
操作.返回true表示预处理成功.
调用processMapping()方法,在此寻找与用户请求相匹配的ActionMapping,如果不存在则返回出错信息
调用processRoles()方法,该方法先判断对应请求的Action是否配置了安全角色,如果配置了安全角色就
调用isUserInRole()方法来确定用户是否具备该角色,如果不具备将返回错误信息.
调用processActionForm()方法,该方法先判断是否为ActionMapping配置了ActionForm,如果配置了
ActionForm,就先从ActionForm的存在范围内查找该ActionForm的实例,如果不存在就创建一个新的实例
,接下来将它保存在合适的范围中,保存时的属性名称为ActionMapping中配置的name属性值.
调用processPopulate()方法.该方法检查ActionMapping是否配置了ActionForm,如果找到就调用
ActionForm的reset()方法,再把请求中的数据装载到ActionForm中.
调用processValidate()方法,如果ActionMapping配置了ActionForm,并且属性validate为true,此时将
调用ActionForm的validate()方法.如果validate()方法返回的ActionErrors对象中包含ActionMessage
对象,说明表单验证失败,此时将ActionErrors对象存储在request的范围中,再把请求发送给
ActionMapping的input属性指定的Web组件.如果ActionForm的validate()返回空则表示验证成功,就继
续执行下一步处理流程.
接下来调用processForward()方法,该方法判断是否在ActionMapping中配置了forward属性,如果配置了
这个属性就调用RequestDispatcher的forward()方法,执行转向,请求处理流程就结束了,否则进行下一
步操作.
调用processInclude()方法,该方法判断是否在ActionMapping中配置了include属性,如果配置了该属性
就调用RequestDispatcher的include()方法,请求处理流程就结束了,否则进行下一步操作.
调用processActionCreate(),该方法用于获取请求对应的Action,它先判断是否在Action缓存中存在这
个Action的实例,如果不存在,就建立一个并将它保存在缓存中.
调用processActionPerferm()方法,该方法调用Action的execute方法,execute方法位于trycatch中,
以便捕获异常.
调用processActionForward()方法,把Action执行之后返回的ActionForward对象作为参数传给它,该方
法根据ActionForward指定的转发路径来执行转发或重定向操作.
Action类的execute方法:
execute方法的参数
ActionMapping:
包含了该Action的配置信息,对应配置文件的action节点
ActionForm:
包含了用户的表单数据,当Struts框架调用execute()方法时,
ActionForm中的数据已经通过了表单的验证.
HttpServletRequest:
当前的Http请求对象
HttpServletResponse:
当前的Http响应对象
该方法返回一ActionForward对象它包含了请求转发的路径信息.
定制Struts控制器组件:
定制Struts的ActionServlet,实际上只需要定制org.apache.struts.action.RequestProcessor类即可
,该类真正包含了Struts在处理Servlet请求时所遵循的控制逻辑,该类的的process方法用来委托处理客
户请求,其中的定义一个预定义方法processPreprocess专门用于实现定制的控制逻辑.
在完成自定义的类后需要在对应模块的配置文件中加入<controller>元素,它的属性type指定自定义的控
制类路径.
例:
<controllerprocessorClass="ctrl.MyProcessor"/>
什么是国际化?
国际化(简称I18N)是指在软件的设计阶段就应该使软件具有支持多种语言和地区的功能.这样当需要应
用中添加对一种新的语言和地区的支持时,不需要对已有的软件返工,无需修改应用的程序代码就能达到
修改的目的一种软件设计方法.
国际化的特征:
当应用需要支持一种新语言时,无需修改应用代码.
文本,消息,图片从源程序中抽取出来,存储在外.
根据用户的语言及地理位置,对与特定文化相关的数据,如日期,时间,货币进行正确的格式化.
可以方便的对应用做出相应的调整,使它适应的新的语言和地区.
Java中对I18N支持类:
Java.util.locale类
locale对象本身不执行格式化及国际化的解析工作,它只是负责传递有关用户的本地信息,这些
信息包括用户的语言,地理位置,操作系统等.
其中的getDefaultLocale()静态方法,可获取缺省的系统本地信息,此信息由JVM初始化.
Web系统的用户本地信息通过request请求对象可获取,通过request.getLocale();可获取请求用
户的本地信息.
Java.util.ResourceBundle类;
在Struts应用中访问Locale对象:
在配置Struts的Cottroller(ActionServlet)时,可以通过设定locale属性来设置是否将用户请求的
locale信息置于session中,缺省的为true,也就是根据用户的请求来却定用户的locale信息.
processLocale()方法把locale信息放入session中会检查,如果session中已存在或locale属性的设置不
为true都不会将locale信息置于session中.在自定义的Action中访问locale对象,Action的基类有提供
getLocale的方法用于获取locale对象.
该方法获取locale的过程为:
首先获取session作用域中的locale对象.
如果session中不存在,再通过HttpServletRequest的getLocale()获取locale对象。
ResourceBundle类:
Java.util.ResourceBundle类提供存放和管理和locale相关的资源的功能。
这些资源包括文本提示,消息
,以及图片名,错误信息,网页标题之类的信息。
Struts框架并没有直接使用java框架下的ResourceBundle类,在Struts框架下主要存在两个类:
org.apache.struts.util.MessageResources
org.apache.struts.util.PropertyMessageResources
这两个类都具有ResourceBundle的功能,其中PropertyMessageResources是MessageResources的
子类。
创建Struts的ResourceBundle:
Struts配置文件中的每个<message-resources>元素定义了一个ResourceBundle,当应用中有多个
ResourceBundle时它们通过key属性值来区分.
如果对应的key属性为空,表示为缺省的ResourceBundle.
例:
<message-resourcenull=“false”parameter=“appsource”>
parameter指定资源包名称.
null:
指定当查找的信息代码不存在时是否终止JSP处理,缺省为true
此处定义一个缺省的ResourceBundle,引用资源文件的基名为:
appsource
当Struts处理Locale为中文的请求时,它会依次寻找如下资源文件:
application_zh_CN.properties
application_zh.properties
application.properties
Struts加载ResourceBundle:
Struts在启动时将每一个ResourceBundle进行加载并且将这些信息存储在一个
org.apache.struts.util.MessageResources类的实例中(实际上是PropertyMessageResources实例),这个
实例存储在ServletContext中,因此任何的Web组件都可以访问到它。
如何访问ResourceBundle?
1、通过编程来访问ResourceBundle
类似于JavaI18N的ResourceBundle类的方法。
如下例:
publicActionForwardexecute(
ActionMappingmap,
ActionFormform,
HttpServletRequestrequest,
HttpServletResponseresponse){
//获取用户请求的本地信息
Localelocale=this.getLocale(request);
//获取资源配置
MessageResourcesmr=this.getResources(request);
//根据用户的本地信息,获取资源中的信息
Stringmsg=mr.getMessage(locale,“hello.i18n.str”);
…
}
2、使用和ResourceBundle绑定的Struts组件
Struts中许多内在的组件都是和ResourceBundle是邦定在一起的,例如:
ActionMessage类
<html:
errors>标签
<bean:
message>标签
在声明异常处理中使用ResourceBundle
联合使用ActionMessage类和<html:
error>标签:
例如在验证用户登录时,如果用户登录不成功提示用户出错的原因,如下:
publicActionForwardexecute(
ActionMappingmap,
ActionFormform,
HttpServletRequestrequest,
HttpServletResponseresponse){
ActionErrorserrors=newActionErrors();//创建一个错误信息集合对象
LoginFormlf=(LoginForm)form;
LoginServiceser=ServiceFac.getLoginService();//验证用户登录
Stringuserid=ser.checkLogin(form.getUser(),form.getPwd());
if(userid!
=null){//用户登录失败产生错误信息
errors.add(“login”,newActionMessage(“login.error”));
}
saveErrors(request,errors);//存储错误信息到请求作用域中
…
}
在JSP页面中可通过<html:
error>标签,读取并显示ActionErrors集合中的ActionMessage对应的文本信息,
例如:
<html:
error>
使用Bean标签库的<bean:
message>标签:
例如使用<bean:
message>显示网页标题
<html>
<head><title>
<bean:
messagekey=“app.title”/>
</title></head>
</html>
在上面的示例中,该标签处理程序首先从session中获取用户的本地信息locale对象,然后从默认的
ResourceBundle中检索与locale对应的资源文件,再从资源文件中读取键值为app.title的字符串,最后
将获取的字符串输出。
<bean:
message>属性
bundle:
需要指定特定的ResourceBundle时使用,对应配置文件中的Resource的key值。
如果不设置采用的就是缺省的ResourceBundle.
key:
指定获取在ResourceBundle中的消息key。
对Struts应用进行国际化:
为了保证在同一JSP页面中能支持多种语言,可以将所有的JSP页面的字符编码方式统一设置为”UTF-8”
<%@pagecontentType=“text/html;charset=UTF-8”%>
UTF-8:
是一种跨平台的字符编码。
注意:
当页面设置为UTF-8的字符编码后,最好将页面进行转码(使用jdk中的native2ascii进行
转码)保存,另外页面所引用的文件如javascript,css,html,jsp文件均需要采用UTF-8编码,如果其中包
含非UTF-8字符(如汉字)需要转码保存。
对文本的国际化:
在JSP页面中不应当直接包含本地化的消息文本,而应当通过<bean:
message>标签从ResourceBundle中获
得文本。
例:
<bean:
messagekey=“app.title”/>
对按钮的国际化:
可通过<bean:
message>为按钮提供国际化的信息,例如:
<html:
submit>
<bean:
messagekey=“form.submit”/>
</html:
submit>
<html:
reset>
<bean:
messagekey=“form.reset”/>
</html:
reset