2

好的,我对这个相同的主题有一个赏金,只有部分答案,所以我要打开这个并简化主题,因为我猜原来的那个太臃肿了。

我面临这样一种情况,我基本上有一个过滤器,它从 servlet 上下文中获取一个 Spring 服务工厂对象,当过滤器调用它的 getService 方法时,这个工厂分配一个 bean 的实例,但我需要访问会话或实际的 httpServletRequest请求的对象,因为我需要请求中的用户 ID。我认为,根据我的阅读,我不应该将它传递给 bean,这不仅因为它不是线程安全的,而且因为它会破坏拥有过滤器的远程服务桥 (CP2JavaWS) 的抽象。

如何让这个 bean 访问会话或 httpServletRequest?

我尝试使用 FacesContext 但它不起作用,因为我认为 bean 不是由 jsp 调用而是由过滤器实例化的。

现在一些代码。

这是我的 web.xml

<display-name>CP2JavaWSTest</display-name>
<welcome-file-list>
    <welcome-file>index.html</welcome-file>
</welcome-file-list>

<error-page>
  <error-code>404</error-code>
  <location>/err.jsp</location>
</error-page>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>
    org.springframework.web.context.request.RequestContextListener
</listener-class>

<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<listener>
    <listener-class>com.cp2javaws.listeners.SpringContextWrapperListener</listener-class>
</listener>

<listener>
    <listener-class>com.bucle.listeners.BCLUserDatabaseContextListener</listener-class>
</listener>

<filter>
    <filter-name>BCLAuthenticationFilter</filter-name>
    <filter-class>com.bucle.filters.BCLAuthenticationFilter</filter-class>
</filter>

<filter>
    <filter-name>BCLAuthorizationFilter</filter-name>
    <filter-class>com.bucle.filters.BCLAuthorizationFilter</filter-class>
</filter>
<filter>
    <filter-name>CPJSonFilter</filter-name>
    <filter-class>com.cp2javaws.filters.CPJSonFilter</filter-class>

</filter>

应用程序上下文:

  <bean id="service1" class="com.bucle.database.BCLDb4oManager" scope="request"/>
  <bean id="service2" class="com.bucle.services.appe.BCLUserCFVC"/>
  <bean id="service3" class="com.bucle.services.appe.BCLUserCustomizedFutureValueCalculator"/>

CPWJavaWS 过滤器

public class CPJSonFilter implements Filter {

    //.. properties

    public void init(FilterConfig filterConfig) 
    throws ServletException {
    //.. init code
    }

    public void destroy() {
        //..
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
        throws IOException, ServletException {


        HttpSession session = ((HttpServletRequest)request).getSession(true); 

        //..Class and method decoding and mapping from JSON

                Class type = null;
                String value = request.getParameter(CP2JavaWSRequestParameterType+paramOrderString);
                if(paramName.indexOf(CP2JavaWSRequestGenericParamSuffix)>0 || request.getParameter(CP2JavaWSRequestParameterType+paramOrderString).equals("id")) {//SAMIR
                    type = Object.class;
                } else {
                    if(paramName.indexOf(CP2JavaWSRequestNullParamSuffix)>0) {
                        String CPClassName = paramName.substring(paramName.indexOf(CP2JavaWSRequestNullParamSuffix)+CP2JavaWSRequestNullParamSuffix.length());
                        try {
                            type = getJavaClassForCPClass(CPClassName);
                        } catch (CP2JavaWSException e) {
                            throw new ServletException("Cannot find corresponding Java class for null argument at index "+paramOrderString+" (passed CP class name is"+CPClassName+")");
                        }
                    } else if(List.class.isAssignableFrom(convertedObject.getClass())) {
                        type = List.class;
                    } else if(Map.class.isAssignableFrom(convertedObject.getClass())) { 
                        type = Map.class;
                    } else {
                        type = convertedObject.getClass();
                    }
                }
                typesOrderedMap.put(new Integer(paramOrderString), type);
            }
        }
        // invoke the service method using the provided service factory class
        Object result = null;
        try {
                Class serviceInterfaceClass = Class.forName(serviceInterfaceName);
                ServiceFactory serviceFactory = (ServiceFactory) filterConfig.getServletContext().getAttribute(ServiceFactory.CP2JAVAWS_SERVICES_FACTORY);
                Object service = serviceFactory.getService(serviceInterfaceClass);


                Method method = service.getClass().getDeclaredMethod(serviceMethodName, (Class[]) typesOrderedMap.values().toArray(new Class[typesOrderedMap.size()]));
                result = method.invoke(service, argumentsOrderedMap.values().toArray());

        } catch(Exception e) {
            throw new ServletException("Error invoking the service method :"+serviceMethodName+" on service "+serviceInterfaceName,e);
        }

        //...Convert result to JSON
            response.setContentType("application/json");
            PrintWriter writer = response.getWriter();
    StringBuffer stb = new StringBuffer();

            //... append result and some other stuff to the string buffer stb

        response.setContentLength(stb.length());
        ((HttpServletResponse)response).setStatus(HttpServletResponse.SC_OK);
        writer.write(stb.toString());
        writer.flush();
    }

    public static Class getJavaClassForCPClass(String CPClassName) throws CP2JavaWSException {
    //... returns the matching Class.class according to a default map like: CPArray -> List.class
    }
}

这是 Spring 上下文监听器:

public class SpringContextWrapperListener implements ServletContextListener {


    private ServletContext context = null;


    public void contextDestroyed(ServletContextEvent event) {
        this.context = null;
        //log.info("Spring Context Destruido");
    }


    public void contextInitialized(ServletContextEvent event) {
        this.context = event.getServletContext();
        ApplicationContext springContext = (ApplicationContext) WebApplicationContextUtils.getRequiredWebApplicationContext(this.context);
        SpringContextWrapper aSpringContextWrapper = new SpringContextWrapper(springContext);
        this.context.setAttribute(ServiceFactory.CP2JAVAWS_SERVICES_FACTORY, aSpringContextWrapper);
    }
}

和工厂:

public class SpringContextWrapper implements ServiceFactory {

private ApplicationContext springContext;

public SpringContextWrapper(ApplicationContext springContext) {

    this.springContext = springContext;
}

public Object getService(Class serviceInterfaceClass) throws CP2JavaWSException {

    Map services =  this.springContext.getBeansOfType(serviceInterfaceClass);
    Iterator it = services.values().iterator();
    if(it.hasNext()) {
        return it.next();
    }
    throw new CP2JavaWSException("can't find service for interface "+serviceInterfaceClass.getName());
}

public Object getService(String serviceName) throws CP2JavaWSException {

    Object service = this.springContext.getBean(serviceName);
    if(service==null) {
        throw new CP2JavaWSException("can't find service for name "+serviceName);
    }
    return service;
}}
4

2 回答 2

2

我不是 100% 确定我理解这个问题,但我认为你可以使用RequestContextHolder你想要做的事情。

ServletRequestAttributes attrs = (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
HttpServletRequest req = attrs.getRequest();

但是,查看一些代码会有所帮助。我怀疑你可以用正确scope的 bean 来实现你想要的。

于 2013-04-30T05:15:29.023 回答
1

您可以使用 threadlocal 在过滤器的方法中存储包装原始 HttpServletRequest 和 HttpServletResponse 的对象doFilter,然后从 bean 中的 threadlocal 访问此包装器对象。以下是您将如何实现它的粗略实现:

public class WebRequest {

    private HttpServletRequest request;

    private HttpServletResponse response;

    public WebRequest(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
    }   
}

class WebRequestUtils {

    private static ThreadLocal<WebRequest> webRequest;

    public static void setWebRequest(WebRequest value)   {
        webRequest.set(value);
    }

    public static WebRequest getWebRequest() {
        return webRequest.get();
    }
}

class CustomFilter {

    doFilter(HttpServletRequest request, HttpServletResponse response) {
        WebRequest webRequest = new WebRequest(request, response);
        WebRequestUtils.setWebRequest(webRequest);
    }
}

class Bean {

    void someMethod() {
        WebRequest webRequest = WebRequestUtils.getWebRequest();
    }
}
于 2013-04-30T05:23:25.303 回答