Struts2的Action调用还是要从FilterDispatcher的#doFilter()方法开始说起。
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
ServletContext servletContext = getServletContext();
String timerKey = "FilterDispatcher_doFilter: ";
try {
UtilTimerStack.push(timerKey);
/* (1) 对请求进行包装 */
request = prepareDispatcherAndWrapRequest(request, response);
ActionMapping mapping;
try {
/* (2) 获得Action Mapping */
mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager());
} catch (Exception ex) {
LOG.error("error getting ActionMapping", ex);
dispatcher.sendError(request, response, servletContext,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
return;
}
if (mapping == null) {// 当Mapping为空时,检查是否访问的为静态资源
String resourcePath = RequestUtils.getServletPath(request);
if ("".equals(resourcePath) && null != request.getPathInfo()) {
resourcePath = request.getPathInfo();
}
if (serveStatic && resourcePath.startsWith("/struts")) {
String name = resourcePath.substring("/struts".length());
findStaticResource(name, request, response);
} else {
// this is a normal request, let it pass through
chain.doFilter(request, response);
}
// The framework did its job here
return;
}
/* (3) 调用被请求的Action的执行方法(例如execute)和拦截器等 */
dispatcher.serviceAction(request, response, servletContext, mapping);
} finally {
try {
ActionContextCleanUp.cleanUp(req);
} finally {
UtilTimerStack.pop(timerKey);
}
}
}
主要有三个部分需要重点说明:
(1) 对请求进行包装;
(2) 获得Action Mapping;
(3) 调用被请求的Action的执行方法(例如execute)和拦截器等。
下面来一一详细说明:
1. 对请求进行包装:request = prepareDispatcherAndWrapRequest(request, response);
下面来看一下#prepareDispatcherAndWrapRequest()的源代码:
protected HttpServletRequest prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException {
Dispatcher du = Dispatcher.getInstance();// (1)
if (du == null) {
Dispatcher.setInstance(dispatcher);
dispatcher.prepare(request, response);// (2)
} else {
dispatcher = du;
}
try {
request = dispatcher.wrapRequest(request, getServletContext());// (3)
} catch (IOException e) {
String message = "Could not wrap servlet request with MultipartRequestWrapper!";
LOG.error(message, e);
throw new ServletException(message, e);
}
return request;
}
(1) 这个方法先是获取一个Dispatcher的实例,获取是通过ThreadLocal的方式,可见Struts2框架为每一个线程都提供了一个Dispatcher对象,所以在编写Action的时候不需要考虑多线程的问题了。
(2) 如果是第一次访问FilterDispatcher,那么du应该为null,这时要调用Dispatcher的#prepare()方法:
public void prepare(HttpServletRequest request, HttpServletResponse response) {
String encoding = null;
if (defaultEncoding != null) {
encoding = defaultEncoding;
}
Locale locale = null;
if (defaultLocale != null) {
locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
}
if (encoding != null) {
try {
request.setCharacterEncoding(encoding);
} catch (Exception e) {
LOG.error("Error setting character encoding to '" + encoding + "' - ignoring.", e);
}
}
if (locale != null) {
response.setLocale(locale);
}
if (paramsWorkaroundEnabled) {
request.getParameter("foo");
}
}
通过源代码可以看出,此方法主要为设置编码和Locale。
(3) 第三步是对请求的包装,request = dispatcher.wrapRequest(request, getServletContext()); 源代码如下:
public HttpServletRequest wrapRequest(HttpServletRequest request, ServletContext servletContext) throws IOException {
if (request instanceof StrutsRequestWrapper) {// 判断request是否是StrutsRequestWrapper的对象,保证对request只包装一次。
return request;
}
String content_type = request.getContentType();
if (content_type != null && content_type.indexOf("multipart/form-data") != -1) {
MultiPartRequest multi = getContainer().getInstance(MultiPartRequest.class);
request = new MultiPartRequestWrapper(multi, request, getSaveDir(servletContext));
} else {
request = new StrutsRequestWrapper(request);
}
return request;
}
判断Content-Type是否是multipart/form-data,如果是的话返回一个MultiPartRequestWrapper的对象处理文件上传,否则返回StrutsRequestWrapper的对象处理普通请求。
分享到:
相关推荐
struts2利用通配符调用同一个Action里面不同的方法,在struts.xml配置文件中将请求方法的不相同部分抽象成“*".
struts 1框架的动态调用也许你会,但是struts2 的动态调用更经典,这个文档让你玩转struts 2 动态调用.......
利用Struts 2框架创建一个web项目chap2_e22,实现用户登录过程。具体要求是在loginAction类中分别用login()和registered()处理用户登录和注册的过程,分别创建login.jsp和register.jsp两个页面实现登录和注册的...
1 在Action实现类方面的对比:Struts 1要求Action类继承一个抽象基类;Struts 1的一个具体问题是使用抽象类编程而不是接口。Struts 2 Action类可以实现一...Struts 2 Action可以通过初始化、设置属性、调用方法来测试。
ajaxt json 调用struts2 action的实例(myeclipse 直接导入运行) 学习点: 1;怎样在页面用ajax调用struts2的action 2;怎样对struts进行配置 3;ajax的运行历程 最简单明了的实例,清晰的帮你弄清上述概念,运行...
JS调用Struts中的ActionJS调用Struts中的ActionJS调用Struts中的Action
第一部分 Strut 2:一个全新的框架 第1章 Struts 2:现代Web框架 2 1.1 Web应用程序:快速学习 2 1.1.1 构建Web应用程序 2 1.1.2 基础技术简介 3 1.1.3 深入研究 6 1.2 Web应用程序框架 7 1.2.1 什么是框架 7 1.2.2 ...
struts2动态调用之通配符,相当于是改进的method动态调用方法,减少对同一action不同method的多次配置
首先,Struts的ActionServlet接收到一个请求,然后根据struts-config.xml的配置定位到相应的mapping (映射);接下来如果form的范围是request或者在定义的范围中找不到这个form,创建一个新的form实例;取得form...
目的:主要为了在一个Action成功后跳转调用另一个程序。 Struts2.xml [html] 代码如下: <?xml version=”1.0″ encoding=”UTF-8″?> <!DOCTYPE struts PUBLIC “-//Apache Software Foundation//DTD ...
struts动态访问调用之一,采用method属性,同一个Action内的不同方法来响应用户请求
很经典的struts2开发实例,其中的action类的写法可以教你很清楚的了解具体的调用过程回给你开发带来很大的帮助
另外,按照惯例,在Struts1.x中只有“execute”方法能调用Action, 但在Struts2中并非必要,任何声明为public String methodName() 方法,都能通过配置来调用Action。 最后,和Struts1.x最大的革命性的不同是,...
Struts2简介以及Struts2的环境配置和Struts2框架实现功能的原理
详细讲解struts2中单个action中多个处理逻辑的配置方法, 以及默认Action的配置.
Namespace、自定义Action、路径问题、通配符、包含模块配置文件、默认Action、接受用户输入、服务器跳转、Action中访问web元素、简单数据校验、调用Action的自定义方法 5struts2国际化 ......... 6 struts2输入校验...
最近修了几个struts2.1升级到2.3后动态方法调用失效的bug,深有感悟, 但是我那种原始方法有一个局限,就是在submit那里写下的action不起作用,就算启动了动态方法调用也不行(我想应该是struts2.3的一个bug),所以...
一个请求在Struts 2框架中的处理大概分为以下几个步骤。 客户端提交一个(HttpServletRequest)请求,如上文在浏览器中输入 http://localhost: 8080/bookcode/ch2/Reg.action就是提交一个(HttpServletRequest)...
2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin) 3 接着FilterDispatcher被调用,...
使用Struts的Action来对数据库进行增、删、改、查四项操作 <br/>1、数据库MySQL,创建数据库 Pagination MySQL.sql用来创建表结构 <br/>连接方式有两种,一种直接JDBC,一种通过连接池,代码中有说明...