Java 基于web的应用程序的设计模式
我正在设计一个简单的基于web的应用程序。我不熟悉这个基于web的领域,我需要你对设计模式的建议,比如如何在Servlet之间分配责任,创建新Servlet的标准,等等 事实上,我的主页上几乎没有实体,对应于每个实体,我们几乎没有添加、编辑和删除等选项。早些时候,我对每个选项使用了一个Servlet,比如Servlet1用于添加entity1,Servlet2用于编辑entity1等等,这样我们就拥有了大量的ServletJava 基于web的应用程序的设计模式,java,design-patterns,jsp,servlets,Java,Design Patterns,Jsp,Servlets,我正在设计一个简单的基于web的应用程序。我不熟悉这个基于web的领域,我需要你对设计模式的建议,比如如何在Servlet之间分配责任,创建新Servlet的标准,等等 事实上,我的主页上几乎没有实体,对应于每个实体,我们几乎没有添加、编辑和删除等选项。早些时候,我对每个选项使用了一个Servlet,比如Servlet1用于添加entity1,Servlet2用于编辑entity1等等,这样我们就拥有了大量的Servlet 现在我们正在改变我们的设计。我的问题是如何准确地选择servlet的职责
现在我们正在改变我们的设计。我的问题是如何准确地选择servlet的职责。每个实体应该有一个Servlet,它将处理所有选项并将请求转发到服务层。或者我们应该为整个页面提供一个servlet,它将处理整个页面请求,然后将其转发到相应的服务层?另外,请求对象是否应该转发到服务层。IMHO,如果从责任分配的角度来看,web应用程序的情况没有太大区别。但是,请在图层中保持清晰。在表示层中保留任何纯粹用于表示目的的内容,例如特定于web控件的控件和代码。只需将实体保留在业务层中,将所有功能(如添加、编辑、删除)等保留在业务层中即可。但是,将它们渲染到浏览器上,以便在表示层中进行处理。对于.Net,ASP.Net MVC模式在保持层之间的分离方面非常好。查看MVC模式。在破旧的MVC模式中,Servlet是“C”-控制器 它的主要工作是执行初始请求评估,然后根据初始评估将处理分派给特定的工作人员。工作人员的职责之一可能是设置一些表示层bean,并将请求转发到JSP页面以呈现HTML。因此,仅出于这个原因,您就需要将请求对象传递给服务层
不过,我不会开始编写原始的
Servlet
类。他们所做的工作是非常可预测和样板的,框架做得非常好。幸运的是,有许多可用的、经过时间考验的候选程序(按字母顺序排列):,举几个例子。一个有点体面的web应用程序由多种设计模式组成。我只提最重要的几点
您希望使用的核心(架构)设计模式是。控制器将由一个Servlet表示,该Servlet(in)根据请求直接创建/使用特定的模型和视图。该模型将由Javabean类表示。这通常在包含动作(行为)的业务模型和包含数据(信息)的数据模型中进一步划分。视图由JSP文件表示,这些文件可以通过EL(表达式语言)直接访问(数据)模型 然后,会根据操作和事件的处理方式而有所不同。受欢迎的有:
- 基于请求(操作)的MVC:这是最简单的实现。(业务)模型直接用于
和HttpServletRequest
对象。您必须自己收集、转换和验证请求参数(大部分)。该视图可以用普通的HTML/CSS/JS表示,并且不在请求之间维护状态。这就是其中之一,并且是有效的HttpServletResponse
- 基于组件的MVC:这更难实现。但是您最终得到了一个更简单的模型和视图,其中所有“原始”Servlet API都被完全抽象掉了。您不需要自己收集、转换和验证请求参数。控制器执行此任务,并在模型中设置收集、转换和验证的请求参数。您所需要做的就是定义直接与模型属性一起工作的操作方法。视图由JSP标记库或XML元素风格的“组件”表示,这些元素反过来生成HTML/CSS/JS。后续请求的视图状态在会话中保持。这对于服务器端转换、验证和值更改事件特别有用。这就是其中之一,并且是有效的
() 首先,控制器部分应该实现(这是一种特殊类型的)。它应该只包含一个servlet,它为所有请求提供一个集中的入口点。它应该根据请求提供的信息创建模型,例如pathinfo或servletpath、方法和/或特定参数。在下面的示例中,业务模型称为
Action
执行操作应该返回一些标识符来定位视图。最简单的方法是将其用作JSP的文件名。将此servlet映射到web.xml
中的特定url模式
,例如/pages/*
,*.do
,甚至只是*.html
在前缀模式的情况下,例如/pages/*
,您可以调用URL等,并提供/WEB-INF/register.jsp
,/WEB-INF/login.jsp
,以及相应的GET和POST操作。如上文所述,注册
、登录
等部分可通过
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Action action = ActionFactory.getAction(request);
String view = action.execute(request, response);
if (view.equals(request.getPathInfo().substring(1)) {
request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response);
}
else {
response.sendRedirect(view); // We'd like to fire redirect in case of a view change as result of the action (PRG pattern).
}
}
catch (Exception e) {
throw new ServletException("Executing action failed.", e);
}
}
public interface Action {
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
public class LoginAction implements Action {
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userDAO.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user); // Login user.
return "home"; // Redirect to home page.
}
else {
request.setAttribute("error", "Unknown username/password. Please retry."); // Store error message in request scope.
return "login"; // Go back to redisplay login form with error.
}
}
}
public static Action getAction(HttpServletRequest request) {
return actions.get(request.getMethod() + request.getPathInfo());
}
actions.put("POST/register", new RegisterAction());
actions.put("POST/login", new LoginAction());
actions.put("GET/logout", new LogoutAction());
// ...
for (Entry entry : configuration) {
actions.put(entry.getKey(), Class.forName(entry.getValue()).newInstance());
}
for (ClassFile classFile : classpath) {
if (classFile.isInstanceOf(Action.class)) {
actions.put(classFile.getAnnotation("mapping"), classFile.newInstance());
}
}