1

そこで、学校のプロジェクトでは、ユーザーが水中生物などに関するレポートを送信できるサイトを作成しました。単純な依存性注入(javax.inject)と、次のようなエラーチェックパターンを使用しました。

ReportService.java

public interface ReportService {
    public static enum ReportServiceErrorsENUM {
        DB_FAILURE, WRONG_COORD // etc
    }
    public Set<ReportServiceErrorsENUM> getLastErrors();
    public int addNewReport(Report report);
}

ReportServiceImpl.java

public class ReportServiceImpl implements ReportService {

    private Set<ReportServiceErrorsENUM> lastErrors;
    private @Inject ReportDAO reportDAO;

    @Override
    public Set<ReportServiceErrorsENUM> getLastErrors() {
        return this.lastErrors;
    }

    @Override
    public int addNewReport(Report report) {
        lastErrors= new HashSet<ReportServiceErrorsENUM>();//throw away previous errors
        UserInput input = report.getUserInput();
        if (input.getLatitude() == null) {
            addError(ReportServiceErrorsENUM.WRONG_COORD);
        }
        // etc etc
        if (reportDAO.insertReport(report) != 0) {
            // failure inserting the report in the DB
            addError(ReportServiceErrorsENUM.DB_ERROR);
        }
        if (lastErrors.isEmpty()) // if there were no errors
            return EXIT_SUCCESS; // 0
        return EXIT_FAILURE;  // 1
    }
}

SubmitReportController.java

@WebServlet("/submitreport")
public class SubmitReportController extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private @Inject ReportService reportService;

    @Override
    protected void doPost(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException {
        Report report = new Report();
        // set the report's fields from the HttpServletRequest attributes
        if(reportService.addNewReport(report) == ReportService.EXIT_FAILURE) {
            for(ReportServiceErrorsENUM error : reportService.getLastErrors())
                // display the errors etc
        } else {
            // display confirmation
        }
    }
}

サーブレットコントローラがサービス(挿入されたもの)を呼び出し、サービスの戻り値をチェックし、エラーが発生した場合はサービスでgetLastErrors()を呼び出して、何が問題だったかなどをユーザーに通知するという考え方です。これはスレッドセーフではないことに注意してください-@Inject'edReportService(reportService)は、サーブレットを使用するすべてのスレッドで共有されます

  1. それは(指を交差させる)ですか?
  2. このエラーメカニズムをどのように改善できますか?

ありがとう

4

2 に答える 2

1

通常、サーブレットの場合、これらの変数 (一般に「状態」と呼ばれます) をコンテナー管理のコンテキストに保持する必要があります。私はこれらのエラーをリクエストスコープに移動します - そうすれば、それらはリクエストオブジェクトに(概念的に)保存され、同じリクエストに取り組んでいるサーブレット/jsp/何でもそれらを見る/編集できます。リクエストが異なれば、データストレージも異なります。

サーブレットからリクエスト スコープを使用するためのサンプル コードは、次の場所にあります: http://www.exampledepot.com/egs/javax.servlet/State.html

于 2012-07-22T19:00:29.730 に答える
1

あなたのデザインはスレッドセーフでもなく、複数のユーザーにサーバーを提供する準備もできていません。複数のユーザー (ブラウザー) が同時にサーブレットにアクセスし、同時にlastErrorsセットにアクセスできるため、スレッドセーフではありません。(はい、サーブレットとサービスのインスタンスは 1 つだけです)。HashSet使用するものはスレッドセーフではありません。

また、2 人の異なるユーザーが同じアプリケーションを使用しようとすると、お互いが送信したレポート (エラー) を上書きしてアクセスすることになります。つまり、ユーザー/セッションごとに状態が存在するはずでしたが、すべてのユーザー間で共有されるグローバル状態があります。

2 番目の問題を修正することにより (ヒントを提供しました: use HTTPSession)、最初の問題が発生する可能性は低くなります。これは、同じセッションへの同時アクセスが発生することはほとんどないためです。ただし、可能です (同時 AJAX 要求、2 つのブラウザー タブ)。それを心に留めておいてください。しかし、今解決すべきもっと重要な問題があります。

于 2012-07-22T19:02:11.497 に答える