Struts2的Action调用(一)

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的对象处理普通请求。

你可能感兴趣的:(多线程,框架,struts,servlet)