如何使用JSF servlet和其余servlet记录每个URI访问

时间:2014-10-16 09:54:44

标签: rest servlets jsf-2

我正在使用默认的JSF servlet和RestEasy servlet来提供URI请求(Wildfly 8.1)。我希望使用@SessionScoped辅助bean记录每个URI请求。 CDI bean(@Named)或ManagedBean(@ManagedBean),以便我可以记录来自此访问者的http请求。

我的要求:

  • 我不想从每个JSF页面调用访问记录, 也不是每个REST资源Java文件。
  • 每个请求都必须可链接到@SessionScoped带注释的辅助bean VisitVisit对象存储:
    • 用户(如果已识别)
    • 开始访问
    • 一个IP地址
    • n列表中的URI请求:JSF资源请求和休息资源请求

我的问题:

  1. 如何在web.xml中注册过滤器,将请求(无论是JSF还是REST)记录到@SessionScoped带注释的辅助bean Visit
  2. 如果我可以访问此支持bean,我如何确保它是同一用户的会话?我不清楚Web容器的这种会话管理。 Web容器如何将请求映射到已知的会话实例?通过默认cookie?
  3. 当然,url-pattern /*上已有一个servlet-mapping,而/restresources/*上有一个servlet映射。对于同一条路径,无法注册2个过滤器,是吗? :

    <filter>
        <filter-name>UriLogger</filter-name>
        <filter-class>com.doe.filters.UriAccessLogger</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>UriLogger</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

1 个答案:

答案 0 :(得分:0)

好。对于其他想要记录每个页面和REST资源访问的人来说。

在web.xml文件中创建过滤器。

<filter>
    <filter-name>UriLogger</filter-name>
    <filter-class>com.doe.filters.UriLoggingFilter </filter-class>
</filter>
<filter-mapping>
    <filter-name>UriLogger</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

另外,创建过滤器类。

package com.doe.webapp.controller.general.filters;

import java.io.IOException;
import java.io.Serializable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;

import com.doe.webapp.controller.general.VisitController;

@Named
@SessionScoped
public class UriLoggingFilter implements Serializable, Filter {

    private static final long serialVersionUID = 1472782644963167647L;
    private static Logger LOGGER = Logger.getLogger(UriLoggingFilter.class);
    private String lastLoggedUri = "";

    FilterConfig filterConfig = null;
    @Inject
    VisitController visitController;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }

    /**
     * Log requests of interest with the VisitController.
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException,
            ServletException {

        // Run the other filters.
        filterChain.doFilter(request, response);

        if (request instanceof HttpServletRequest) {
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            String uri = httpServletRequest.getRequestURI();

            String regex = "((/{1}\\w+$)|(/{1}\\w+\\.jsf$))";
            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(uri);
            while (m.find()) {
                LOGGER.info("match " + m.group());

                if (!lastLoggedUri.equals(uri)) {
                    visitController.saveUriRequest(httpServletRequest);
                    lastLoggedUri = uri;
                } else {
                    LOGGER.warn("Multiple URI access to the same resource of the same user: " + uri);
                }
                break;
            }
        }

    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }
}

在此代码中,我删除了重复请求的日志记录。仅记录jsf页面请求和REST资源请求。因此,没有图像,css或js请求。根据您自己的需要调整RegEx。我使用saveUriRequest注释了EJB函数@Asynchronous,以避免响应延迟延迟。

回答我自己的问题:

  1. 过滤器将获取每个http请求 - 无论是JSF页面还是REST资源调用。使用@Named和@SessionScopedFilter注释为CDI bean。现在,每个访问者都有一个过滤器。注意事项 - 如果您拥有大量不同的用户,请不要这样做。这将迅速带来您可用的记忆。或者,您可以将其标记为@ApplicationScoped并从ServletRequest request标头实例获取访客ID,并将请求分配给访问者。此外,这很容易遭到拒绝服务攻击。 (我只是出于内部目的使用它。)
  2. 是的,Web容器在jsessionid之间通过ServletRequest request来区分会话。
  3. 希望这对某人也有帮助。