因此對於一個學校項目,我們創建了一個用戶可以提交水下生活報告等的網站。我們使用簡單的依賴注入(javax.inject)和錯誤檢查模式如下:Servlets + injection -multithreading的問題
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
}
}
}
的想法是,在Servlet控制器調用服務(將其注入),然後檢查服務的返回值,如果有一個錯誤在服務調用getLastErrors() - 通知什麼地方出了錯等用戶現在我剛剛意識到這不是線程安全的 - 在@ Inject'ed ReportService的(ReportService的)將使用servlet
- 是它跨越了所有的線程(共享手指)?
- 如何改善這種錯誤機制?
感謝
不幸的是,這套錯誤屬於服務類 - 我沒有看到從那裏獲取請求的方式(?) – 2012-07-22 19:09:56
處理此問題的最簡單方法如下所示: class ServiceState {private Set lastErrors} 然後在你的servlet中--ServiceState stateForThisRequest = new ...; ReportService。addNewReport(report,stateForThisRequest); 之後你添加stateForThisRequest請求(在一些已知的字符串鍵)供任何其他處理該請求使用(我假設你有一個jsp或東西的顯示?) –
radai
2012-07-22 19:16:58
有可能某種方式來注入一些事務或會話上下文到你的服務中(不真正知道CDI - javax.inject),但這樣就足夠了。像Tomasz說的 - 在同一個會話上可能有多個請求 - 這就是爲什麼請求範圍最適合保持這個請求。 – radai 2012-07-22 19:19:06