多个动态 URI 的单个操作类在并发请求时抛出异常

发布于 2024-09-30 00:35:52 字数 1304 浏览 3 评论 0原文

我使用 Struts2 作为控制器开发了一个网站,并将其与 Spring 和 Hibernate 集成以执行业务逻辑和数据库工作。该网站的 URI 为 http://my.domian.com/URI;其中 {URI} 是通过管理 cms 动态生成的。每个 uri 到 servlet 的映射都是在 Apache mod_rewrite 的帮助下完成的,如下所示:(

RewriteCond %{HTTP_HOST} ^www\.domain\.com
RewriteRule ^([a-zA-Z0-9_-]+)$ /dynamic\.action?f=$1 [QSA,L]  

在提供任何进一步信息之前,这是一种好的且合适的方法吗?)

struts 配置只是一种典型的学术配置,如下所示:

<package name="Default" extends="struts-default" namespace="/">  
    ...  
    <action name="dynamic" class="DynamicContentAction">  
        <result name="index">/content/web/dynamic/index.jsp</result>  
    </action>  
</package>

DynamicContentAction 正在扩展 ActionSupport并实现 ServletRequestAware、ServletContextAware。我正在检查几件事(例如被识别为子域的当前访问语言),在数据库中查找请求的 uri 是否有效,生成该 uri 的内容并设置几个运行时全局变量(例如当前访问页面 ID、由于当前访问语言而导致的布局配置...)并将其放在该 servlet 中的 Request 对象上。

一切看起来都很好,甚至工作得很好,除非单个用户同时请求太多动态页面。 “太多”对我来说至少是 9-10 页。在这种情况下,它会抛出异常,不同的异常!有时 HttpServletRequest 请求为 null,有时 ServletContext servletContext 为 null,有时这些都可以,但运行时变量为 null,用于业务逻辑或数据库查询。

我用谷歌搜索了一下,发现这个动作正在“按请求”实例化。不是这样吗?如果每个请求都有一个操作,那么这个冲突或“可空性问题”有什么问题。除了支柱的线程之外,我应该在该操作中做一些类似线程的事情吗?

如果您能帮助我或为我指明方向,我将不胜感激。

I've developed a web site using Struts2 as a controller and integrated it with Spring and Hibernate to do the business logic and DB stuff. The website's URIs are http://my.domian.com/URI; which {URI} is dynamically generated thorough the admin cms. The mapping of each uri to the servlet are done with help of Apache mod_rewrite, as follow:

RewriteCond %{HTTP_HOST} ^www\.domain\.com
RewriteRule ^([a-zA-Z0-9_-]+)$ /dynamic\.action?f=$1 [QSA,L]  

(Before any further information, is this a good and suitable approach?)

The struts configuration is just a typically-academic one as:

<package name="Default" extends="struts-default" namespace="/">  
    ...  
    <action name="dynamic" class="DynamicContentAction">  
        <result name="index">/content/web/dynamic/index.jsp</result>  
    </action>  
</package>

DynamicContentAction is extending ActionSupport and implementing ServletRequestAware, ServletContextAware. I'm checking a couple of things (such as a current visiting language which is identified as a subdomain), looking up in the database that the requested uri is valid or not, generating that uri's content and setting a couple of runtime global variables (such as current visiting page id, layout config due to current visiting language ...) and put it on a Request object in this servlet.

Everything looks good and even works perfectly ok, unless too many dynamic pages being requested by a single user concurrently. "Too Many" in my case is at least 9-10 pages. In this case it throws exceptions, different ones! Sometimes the HttpServletRequest request is null, sometimes ServletContext servletContext is null, some other times these are ok, but the runtime variables are null which is used in business logic or db querying.

I've googled about it and found out that this action is being instantiated "Per Request". Isn't this so? If there is an action per request, what's wrong with this conflict or "nullability thing". Should I do some thread-like thing in that action, beyond the threading of struts?

I'd be so appreciated if you could help me out or point me a direction.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

海拔太高太耀眼 2024-10-07 00:35:52

这是 DynamicContentAction.java 的简化版本,

public class DynamicContentAction extends ActionSupport implements ServletRequestAware, ServletContextAware {
    private HttpServletRequest request;
    private ServletContext servletContext;

    private ResourceSelectorService resourceSelectorService;

    private String f = null;

    public String execute() {
        if ( f != null ) {
            HashMap<String, Object> resolvedURI = resourceSelectorService.resolveURI(f);

            if ( resolvedURI.get("ERROR").equals(true) ) {
                //Generating nice 404 error page content
            } else {
                //Generating Content
                //and put it on request object as:
                //request.setAttribute("attrName", resourceContent);
            }
        }

        else {
            //Generating nice 404 error page content
        }

        request = null;
        servletContext = null;

        f = null;

        return "index";
    }

    @Override
    public void setServletRequest(HttpServletRequest request) {
        this.request = request;  
    }

    @Override
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;  
    }

    public void setF(String f) {
        this.f = f;
    }

    public String getF() {
        return f;
    }
}

当我写这篇文章时,我了解到这个类不是线程安全的。是吗?所以我对其进行了一些更改,如下所示:

这是 DynamicContentAction.java 的较新版本

public class DynamicContentAction extends ActionSupport {
    private ResourceSelectorService resourceSelectorService;

    private String f = null;

    public String execute() {
        if ( f != null ) {
            final HttpServletRequest request = ServletActionContext.getRequest();
            final ServletContext servletContext = ServletActionContext.getServletContext();

            HashMap<String, Object> resolvedURI = resourceSelectorService.resolveURI(f);

            if ( resolvedURI.get("ERROR").equals(true) ) {
                //Generating nice 404 error page content
            } else {
                //Generating Content
                //and put it on request object as:
                //request.setAttribute("attrName", resourceContent);
            }
            f = null;
        }

        else {
            //Generating nice 404 error page content
        }

        return "index";
    }

    public void setF(String f) {
        this.f = f;
    }

    public String getF() {
        return f;
    }
}

,Null thing 问题几乎消失了,但与生成的内容仍然存在冲突。例如,如果用户尝试打开:

http://www.domain.com/A
http://www.domain.com/B
http://www.domain.com/C
http://www.domain.com/D
http://www.domain.com/E

同时,所有页面都会在浏览器中呈现,但 A 的内容显示在 A 和 B 中,C 是正确的,并且很有可能 D 和 E 的内容也不正确。

Here is simplified version of DynamicContentAction.java

public class DynamicContentAction extends ActionSupport implements ServletRequestAware, ServletContextAware {
    private HttpServletRequest request;
    private ServletContext servletContext;

    private ResourceSelectorService resourceSelectorService;

    private String f = null;

    public String execute() {
        if ( f != null ) {
            HashMap<String, Object> resolvedURI = resourceSelectorService.resolveURI(f);

            if ( resolvedURI.get("ERROR").equals(true) ) {
                //Generating nice 404 error page content
            } else {
                //Generating Content
                //and put it on request object as:
                //request.setAttribute("attrName", resourceContent);
            }
        }

        else {
            //Generating nice 404 error page content
        }

        request = null;
        servletContext = null;

        f = null;

        return "index";
    }

    @Override
    public void setServletRequest(HttpServletRequest request) {
        this.request = request;  
    }

    @Override
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;  
    }

    public void setF(String f) {
        this.f = f;
    }

    public String getF() {
        return f;
    }
}

as I'm writing this post, I have came to the knowledge that this class is NOT thread-safe. Is it? So I've changed it a little bit as follow:

Here is newer version of DynamicContentAction.java

public class DynamicContentAction extends ActionSupport {
    private ResourceSelectorService resourceSelectorService;

    private String f = null;

    public String execute() {
        if ( f != null ) {
            final HttpServletRequest request = ServletActionContext.getRequest();
            final ServletContext servletContext = ServletActionContext.getServletContext();

            HashMap<String, Object> resolvedURI = resourceSelectorService.resolveURI(f);

            if ( resolvedURI.get("ERROR").equals(true) ) {
                //Generating nice 404 error page content
            } else {
                //Generating Content
                //and put it on request object as:
                //request.setAttribute("attrName", resourceContent);
            }
            f = null;
        }

        else {
            //Generating nice 404 error page content
        }

        return "index";
    }

    public void setF(String f) {
        this.f = f;
    }

    public String getF() {
        return f;
    }
}

and the Null thing problem is almost gone, but there is still conflict with the generated content. For example if user try to open:

http:// www.domain.com/A
http:// www.domain.com/B
http:// www.domain.com/C
http:// www.domain.com/D
http:// www.domain.com/E

simultaneously, all of the pages will be rendered in browser, but the content of A is shown in A and B, C is correct, and there is a very good chance that the content of D and E are incorrect too.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文