因此,对于一个学校项目,我们创建了一个网站,用户可以在这里提交关于水下生活等的报告。我们使用了简单的依赖项注入(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
}
}
}
这个想法是Servlet控制器调用服务(注入的),然后检查服务的返回值,并在出现错误时调用服务上的getLastErrors(),以通知用户出了什么问题等。现在我刚刚意识到这不是线程安全的-@Inject'edReportService(ReportService)将由所有使用Servlet 的线程共享
- 是(交叉手指)吗
- 如何改进这种错误机制
感谢
通常,对于servlet,您希望将这些变量(通常称为"state")保留在一些容器管理的上下文中。我会将这些错误转移到请求范围,这样它们就存储在请求对象上(概念上),任何处理同一请求的servlet/jsp/任何东西都可以看到/编辑它们。不同的请求意味着不同的数据存储。
可以在这里找到使用servlet请求范围的示例代码:http://www.exampledepot.com/egs/javax.servlet/State.html
您的设计既不是线程安全的,也不准备为多个用户提供服务器。它不是线程安全的,因为几个用户(浏览器)可以同时访问servlet,然后同时访问lastErrors
集。(是的,servlet和您的服务只有一个实例)。您使用的HashSet
不是线程安全的。
此外,如果两个不同的人尝试使用同一个应用程序,他们将覆盖并可以访问彼此提交的报告(错误)。换句话说,在所有用户之间共享全局状态,而每个用户/会话应该有一个状态。
通过修复第二个问题(我给了你一个提示:使用HTTPSession
),你不太可能看到第一个问题。这是因为很少看到对同一会话的并发访问。但这是可能的(并发AJAX请求,两个浏览器选项卡)。记住这一点,但现在还有更重要的问题需要解决。