由于项目需求的需要,要在原来用Struts2的框架之上集成webservice,因为之前单单做webservice的时候没有多大问题,使用Spring 和 Xfire就可以轻松地发布服务,但是,当和Struts2集成的时候问题确出现了。因为原来在web.xml中,struts2过滤了/*,即把根目录下得所有目录都进行了过滤,而webservice的目录我定义为/services/*,这样一来,客户端访问该web服务的时候就被strust2过滤器当成无效链接过滤了。

 struts2 集成webservice 的方法_struts webservice cx


 struts2 集成webservice 的方法_struts webservice cx_02


问题找到了,所以解决办法也很容易找到,有下面两种方式:
方式一:struts2不要过滤根目录下所有的文件目录,可以用/*.action,/*.do,/*.jsp的形式等等。或者在链接action的时候创立一个命名空间如my,然后struts2就只过滤my/*,这样就不会影响service/*的东西了。
方式二:感谢http://blog.csdn.net/lishengbo/article/details/5474044 提供的思路,修改struts2 dispatcher的内容,因为dispatcher里面有个方式dofilter,他得功能是把过滤请求传递给下面一个过滤器,这样就把当前的请求放行了。所以可以在dofilter里面做下处理,如果请求的链接种包含了service.那就放行,代码如下所示:
if(request.getRequestURI().contains("services"))
       {

        chain.doFilter(req,res);
       }


1.如果在struts2.13之前,可以用以下方法。


在web.xml里面加入了struts2的过滤类:
<filter>
   <filter-name>struts2</filter-name>
   <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
 </filter>

所以,我们要重写这个类,可以在src下建立一个org.apache.struts2.dispatcher.FilterDispatcher类,或者自己指定一个位置,然后在web.xml中修改下对应的struts2的对应类即可。
我采用了方式二解决了问题。因为struts2监听所有的请求比较好,只对一些有要求的请求才放行。

修改后的FilterDispatcher.java的源代码如下:

package org.apache.struts2.dispatcher;

import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.RequestUtils;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.dispatcher.ng.filter.FilterHostConfig;
import org.apache.struts2.util.ClassLoaderUtils;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationProvider;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import com.opensymphony.xwork2.util.profiling.UtilTimerStack;

*
* @see ActionMapper
* @see ActionContextCleanUp
* @see org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
* @see org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter
* @see org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter
*/
public class FilterDispatcher implements StrutsStatics, Filter {

   /**
    * Provide a logging instance.
    */
   private Logger log;

   /**
    * Provide ActionMapper instance, set by injection.
    */
   private ActionMapper actionMapper;

   /**
    * Provide FilterConfig instance, set on init.
    */
   private FilterConfig filterConfig;

   /**
    * Expose Dispatcher instance to subclass.
    */
   protected Dispatcher dispatcher;

   /**
    * Loads stattic resources, set by injection
    */
   protected StaticContentLoader staticResourceLoader;

   /**
    * Initializes the filter by creating a default dispatcher
    * and setting the default packages for static resources.
    *
    * @param filterConfig The filter configuration
    */
   public void init(FilterConfig filterConfig) throws ServletException {
       try {
           this.filterConfig = filterConfig;

           initLogging();

           dispatcher = createDispatcher(filterConfig);
           dispatcher.init();
           dispatcher.getContainer().inject(this);

           staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig));
       } finally {
           ActionContext.setContext(null);
       }
   }

   private void initLogging() {
       String factoryName = filterConfig.getInitParameter("loggerFactory");
       if (factoryName != null) {
           try {
               Class cls = ClassLoaderUtils.loadClass(factoryName, this.getClass());
               LoggerFactory fac = (LoggerFactory) cls.newInstance();
               LoggerFactory.setLoggerFactory(fac);
           } catch (InstantiationException e) {
               System.err.println("Unable to instantiate logger factory: " + factoryName + ", using default");
               e.printStackTrace();
           } catch (IllegalAccessException e) {
               System.err.println("Unable to access logger factory: " + factoryName + ", using default");
               e.printStackTrace();
           } catch (ClassNotFoundException e) {
               System.err.println("Unable to locate logger factory class: " + factoryName + ", using default");
               e.printStackTrace();
           }
       }

       log = LoggerFactory.getLogger(FilterDispatcher.class);

   }

   /**
    * Calls dispatcher.cleanup,
    * which in turn releases local threads and destroys any DispatchListeners.
    *
    * @see javax.servlet.Filter#destroy()
    */
   public void destroy() {
       if (dispatcher == null) {
           log.warn("something is seriously wrong, Dispatcher is not initialized (null) ");
       } else {
           try {
               dispatcher.cleanup();
           } finally {
               ActionContext.setContext(null);
           }
       }
   }

   /**
    * Create a default {@link Dispatcher} that subclasses can override
    * with a custom Dispatcher, if needed.
    *
    * @param filterConfig Our FilterConfig
    * @return Initialized Dispatcher
    */
   protected Dispatcher createDispatcher(FilterConfig filterConfig) {
       Map<String, String> params = new HashMap<String, String>();
       for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements();) {
           String name = (String) e.nextElement();
           String value = filterConfig.getInitParameter(name);
           params.put(name, value);
       }
       return new Dispatcher(filterConfig.getServletContext(), params);
   }

   /**
    * Modify state of StrutsConstants.STRUTS_STATIC_CONTENT_LOADER setting.
    * @param staticResourceLoader val New setting
    */
   @Inject
   public void setStaticResourceLoader(StaticContentLoader staticResourceLoader) {
       this.staticResourceLoader = staticResourceLoader;
   }

   /**
    * Modify ActionMapper instance.
    * @param mapper New instance
    */
   @Inject
   public void setActionMapper(ActionMapper mapper) {
       actionMapper = mapper;
   }

   /**
    * Provide a workaround for some versions of WebLogic.
    * <p/>
    * Servlet 2.3 specifies that the servlet context can be retrieved from the session. Unfortunately, some versions of
    * WebLogic can only retrieve the servlet context from the filter config. Hence, this method enables subclasses to
    * retrieve the servlet context from other sources.
    *
    * @return the servlet context.
    */
   protected ServletContext getServletContext() {
       return filterConfig.getServletContext();
   }

   /**
    * Expose the FilterConfig instance.
    *
    * @return Our FilterConfit instance
    */
   protected FilterConfig getFilterConfig() {
       return filterConfig;
   }

   /**
    * Wrap and return the given request, if needed, so as to to transparently
    * handle multipart data as a wrapped class around the given request.
    *
    * @param request  Our ServletRequest object
    * @param response Our ServerResponse object
    * @return Wrapped HttpServletRequest object
    * @throws ServletException on any error
    */
   protected HttpServletRequest prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException {

       Dispatcher du = Dispatcher.getInstance();

       // Prepare and wrap the request if the cleanup filter hasn't already, cleanup filter should be
       // configured first before struts2 dispatcher filter, hence when its cleanup filter's turn,
       // static instance of Dispatcher should be null.
       if (du == null) {

           Dispatcher.setInstance(dispatcher);

           // prepare the request no matter what - this ensures that the proper character encoding
           // is used before invoking the mapper (see WW-9127)
           dispatcher.prepare(request, response);
       } else {
           dispatcher = du;
       }

       try {
           // Wrap request first, just in case it is multipart/form-data
           // parameters might not be accessible through before encoding (ww-1278)
           request = dispatcher.wrapRequest(request, getServletContext());
       } catch (IOException e) {
           String message = "Could not wrap servlet request with MultipartRequestWrapper!";
           log.error(message, e);
           throw new ServletException(message, e);
       }

       return request;
   }

   /**
    * Process an action or handle a request a static resource.
    * <p/>
    * The filter tries to match the request to an action mapping.
    * If mapping is found, the action processes is delegated to the dispatcher's serviceAction method.
    * If action processing fails, doFilter will try to create an error page via the dispatcher.
    * <p/>
    * Otherwise, if the request is for a static resource,
    * the resource is copied directly to the response, with the appropriate caching headers set.
    * <p/>
    * If the request does not match an action mapping, or a static resource page,
    * then it passes through.
    *
    * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
    */
   public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
       HttpServletRequest request = (HttpServletRequest) req;
       //System.out.println(request.getRequestURI());
       //System.out.println(request.getRequestURI().contains("services"));
       if(request.getRequestURI().contains("services"))
       {

        chain.doFilter(req,res);
       }
       else
       {
           HttpServletResponse response = (HttpServletResponse) res;
              ServletContext servletContext = getServletContext();

              String timerKey = "FilterDispatcher_doFilter: ";
              try {

                  // FIXME: this should be refactored better to not duplicate work with the action invocation
                  ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
                  ActionContext ctx = new ActionContext(stack.getContext());
                  ActionContext.setContext(ctx);

                  UtilTimerStack.push(timerKey);
                  request = prepareDispatcherAndWrapRequest(request, response);
                  ActionMapping mapping;
                  try {
                      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) {
                      // there is no action in this request, should we look for a static resource?
                      String resourcePath = RequestUtils.getServletPath(request);

                      if ("".equals(resourcePath) && null != request.getPathInfo()) {
                          resourcePath = request.getPathInfo();
                      }

                      if (staticResourceLoader.canHandle(resourcePath)) {
                          staticResourceLoader.findStaticResource(resourcePath, request, response);
                      } else {
                          // this is a normal request, let it pass through
                          chain.doFilter(request, response);
                      }
                      // The framework did its job here
                      return;
                  }

                  dispatcher.serviceAction(request, response, servletContext, mapping);

              } finally {
                  try {
                      ActionContextCleanUp.cleanUp(req);
                  } finally {
                      UtilTimerStack.pop(timerKey);
                  }
              }
       }

   }
}

2.如果在struts2.13之后,一般不提倡再用org.Apache.struts2.FilterDispatcher,而是用org.Apache.struts2.ng.filter.StrutsPrepareAndExecuteFilter.

然后自己写个过滤类,继承StrutsPrepareAndExeuteFilter即可。重写里面的doFilter方法。

web.xml里面的过滤器类片段

 <filter>
   <filter-name>struts2</filter-name>
   <filter-class>Myfilter.MyFilter</filter-class>
 </filter>

MyFilter.java源代码

package Myfilter;

import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyFilter extends StrutsPrepareAndExecuteFilter{         //修改struts2 默认的过滤器

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

           HttpServletRequest request = (HttpServletRequest) req;
           HttpServletResponse response = (HttpServletResponse) res;
           System.out.println(request.getRequestURI());
           System.out.println(request.getRequestURI().contains("services"));
           if(request.getRequestURI().contains("services"))              //如果是访问webservice 这不进行过滤
           {
            chain.doFilter(req,res);
           }
           else{
           try {
               prepare.setEncodingAndLocale(request, response);
               prepare.createActionContext(request, response);
               prepare.assignDispatcherToThread();
               if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
                   chain.doFilter(request, response);
               } else {
                   request = prepare.wrapRequest(request);
                   ActionMapping mapping = prepare.findActionMapping(request, response, true);
                   if (mapping == null) {
                       boolean handled = execute.executeStaticResourceRequest(request, response);
                       if (!handled) {
                           chain.doFilter(request, response);
                       }
                   } else {
                       execute.executeAction(request, response, mapping);
                   }
               }
           } finally {
               prepare.cleanupRequest(request);
           }
       }
    }


}