2017-12-06 7 views
0

PHP/LaravelのバックグラウンドからJavaを使用してWebアプリケーション・プログラミングを行うことを望んでいます(約8年前に大学で学んだことがあります) 。Webアプリケーション:シングルトンパターンを使用したサーブレット・スレッドの安全性

サーブレットやサーブレットコンテナのほか、Jetty、Tomcatなどの一般的なWebサーバ/サーブレットコンテナテクノロジのような基本的なコンセプトのほとんどが、また、Java EEに関するかなりの研究を試みました。

私はこのテーマについての知識を蓄積したいので、私はフレームワークを使いたくないので、実際に自分自身を学習の練習として構築したいと考えています。しかし、私はまた、Spring MVC、Struts、Play、Vaadinなど、いくつかのフレームワークをかなり見てきました。

私はMavenプロジェクトをセットアップしました。私はweb.xmlファイルセットを持っています私が作成したサーブレットを指していて、私は自分の「フレームワーク」にエントリーポイントを構築しようとしています。

のsrc /メイン/ webappの/ WEB-INF/web.xmlの

<servlet> 
    <servlet-name>Application</servlet-name> 
    <servlet-class>com.mypackage.Application</servlet-class> 
</servlet> 

<servlet-mapping> 
    <servlet-name>Application</servlet-name> 
    <url-pattern>/*</url-pattern> 
</servlet-mapping> 

のsrc /メイン/ javaの/ COM/mypackageと/ Application.java

package com.mypackage; 

import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import java.io.IOException; 

public class Application extends HttpServlet { 
    @Override 
    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     // 
    } 
} 

だから今私はシングルトンパターンを使用する独自のIoCコンテナを作成したい(私はこれが通常避けられ、アンチパターンと見なされることを知っている)ので、アプリケーションの他の部分から簡単にアクセスできます:

のsrc /メイン/ javaの/ COM/mypackageと/ Container.java

package com.mypackage; 

import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

public class Container { 
    private static Container instance; 

    public static Container make(HttpServletRequest request, HttpServletResponse response) { 
     return instance = new Container(); 
    } 

    public static Container getInstance() { 
     if (instance == null) { 
      // Throw an exception 
     } 

     return instance; 
    } 

    private Container(HttpServletRequest request, HttpServletResponse response) { 
     // ... 
    } 
} 

私は自分のアプリケーションのエントリポイントとして、すべてのリクエスト/レスポンスサイクルのコンテナオブジェクト(またはすべてのサーブレット)を作成したいです。だから私はこのような何かを行うになります

@Override 
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    Container container = Container.make(request, response); 

    // Do stuff with container and eventually respond to the client 
} 

は、今私は、スレッドの安全性は、それがサーブレットに来るとき関心事である、とサーブレットインスタンスのプロパティは、スレッド間で共有されていることを知っているが、私の質問は、に特異的に関連しますContainerオブジェクト私はシングルトンパターンとスレッドセーフを使って作成しています。

私の現在のアプローチはスレッドセーフであると考えられますか?そうでない場合、なぜ、それをスレッドセーフにすることができますか?私のContainerインスタンスを各スレッド間で共有することは実際には望んでおらず、入ってくるリクエスト/レスポンスごとに別のコンテナが必要なことに注意してください。

サーブレットクラスのserviceメソッド内に新しいオブジェクトを作成し、その新しいオブジェクトでコンテナのインスタンスを作成するのは、スレッドセーフ(または推奨される方法)ですか?例えば

public class Something { 
    public Something(HttpServletRequest request, HttpServletResponse response) { 
     Container.make(request, response); 
    } 
} 



@Override 
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    Something something = new Something(request, response); 

    // Do stuff with container and eventually respond to the client 
} 

最後に、サーブレット・コンテナがサーブレット・インスタンスを再使用しているためにスレッド・セーフという問題が発生したと仮定して正しいでしょうか? Java EE documentation

サーブレットのライフサイクルは、サーブレットがデプロイされているコンテナによって制御されます。要求がサーブレットにマップされると、コンテナは次の手順を実行します。

サーブレットのインスタンスが存在しない場合は、Webコンテナ

は、サーブレットクラスをロードします。

サーブレットクラスのインスタンスを作成します。

initメソッドを呼び出してサーブレットインスタンスを初期化します。初期化については、「サーブレットの初期化」を参照してください。

+0

現在の 'Container'コードには、スレッドセーフであるかどうかを伝えるのに十分なコードがありません。あなたがシングルトンを持っている必要がある場合は、Javaでシングルトンを書く方法をGoogleに教えてください。 'Container'を共有する必要がなければ、サーブレットの内部で' Container c = new Container() 'を実行しないのはなぜですか? – tsolakp

+0

これまで以上にコードはありません。私はシングルトンのパターンを使用したいと思うし、それを書く方法を知っています。実際には、今のところコンテナクラスはスレッドセーフではないと確信しています。私の質問は、私のシングルトンContainerクラスがスレッドセーフであるかどうかとは関係がありません。私が現在行っている方法でサーブレット内のシングルトンクラスを開始すると、私のシングルトンインスタンス他のスレッド間で共有されるか、要求/応答サイクルごとに1回存在するかどうか – Jonathon

+0

'Container.make(request、response)'は、あなたがそのメソッドを呼び出していて、 'getInstance'を無視している限り、幾分安全です。 'Container c = new Container()'とほぼ同じです。私がそのメソッドが何をしているのかわからないので、 'Container.boot'アプローチに対するCantのコメント。 – tsolakp

答えて

0

サーブレットでインスタンスを作成すると、サーブレットインスタンスが再利用されるためスレッドセーフではありません。

SingletonまたはApplicationScopedオブジェクトには、アプリケーション全体で1つのコピーしかありません。あなたがオブジェクトのインスタンスが1つだけ存在することを確認する場合は、@ApplicationScopedでクラスに注釈を付ける:

@ApplicationScoped 
public class Something { 
    //do stuff 
} 

そして、サーブレットでそれを注入:

public class SomeServlet extends HttpServlet { 

    @Inject 
    Something obj; 

    @Override 
    public void service(HttpServletRequest request, HttpServletResponse response) { 
    //do stuff 
    } 

} 

を使用すると、クラスがしたいの代わりにした場合リクエストごとに一意になるように使用している場合は、代わりにクラスRequestScopedを作成してください。同様に:

@RequestScoped 
public class Something { 
    //do stuff 
} 

詳細については、CDIチュートリアルhttps://docs.oracle.com/javaee/6/tutorial/doc/giwhl.htmlを参照してください。これには、サーブレットコンテナだけでなく、CDIすなわちPayaraを持つアプリケーションサーバを使用する必要があることに注意してください。

関連する問題