因此对于一个学校项目,我们创建了一个用户可以提交水下生活报告等的网站。我们使用简单的依赖注入(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