web应用程序设计java_java – 设计模式基于web的应用程序

有点像web应用程序组成的混合设计模式。我只提到最重要的。

您希望使用的核心(架构)设计模式是Model-View-Controller pattern.控制器将由Servlet表示,该Servlet根据请求直接创建/使用特定的模型和视图。该模型将由Javabean类来表示。这通常在包含动作(行为)的业务模型和包含数据(信息)的数据模型中进一步可分割。视图由具有通过EL(表达式语言)直接访问(数据)模型的JSP文件表示。

然后,基于如何处理动作和事件存在变化。流行的是:

>基于请求(动作)的MVC:这是最简单的实现。 (业务)模型直接使用HttpServletRequest和HttpServletResponse对象。你必须自己收集,转换和验证请求参数(大部分)。视图可以由纯原生HTML / CSS / JS表示,并且不会在请求之间维护状态。这是其中Spring MVC,Struts和Stripes工作。

>基于组件的MVC:这更难实现。但是你最终得到一个更简单的模型和视图,其中所有的“原始”Servlet API被完全抽象。您不应该需要自己收集,转换和验证请求参数。 Controller执行此任务,并在模型中设置收集,转换和验证的请求参数。所有你需要做的是定义与模型属性直接工作的动作方法。视图在JSP taglib或XML元素的风格中由“组件”表示,依次生成HTML / CSS / JS。会话中维护后续请求的视图的状态。这对服务器端转换,验证和值更改事件特别有用。这是其中JSF,Wicket和Play!工作。

作为一个附注,爱好周围与自己的MVC框架是一个非常好的学习练习,我建议它,只要你保留为个人/私人的目的。但一旦你去专业,那么强烈建议选择一个现有的框架,而不是重塑自己的。学习一个现有的和完善的框架比起开发和维护一个强大的框架需要更长的时间。

在下面的详细解释中,我将限制自己基于请求的MVC,因为这更容易实现。

首先,控制器部分应该实现Front Controller pattern(这是一种特殊类型的Mediator pattern)。它应该只包含一个servlet,它提供了所有请求的集中入口点。它应该基于请求可用的信息创建模型,例如pathinfo或servletpath,方法和/或特定参数。业务模型在下面的HttpServlet示例中被称为Action。

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);

}

}

执行操作应返回一些标识符以定位视图。最简单的是使用它作为JSP的文件名。将此servlet映射到web.xml中的特定url模式,例如。 / pages / *,* .do甚至只是* .html。

在前缀模式的情况下,例如/ pages / *,然后可以调用像http://example.com/pages/register,http://example.com/pages/login等的URL,并提供/WEB-INF/register.jsp,/WEB-INF/login.jsp与适当的GET和POST操作。零件寄存器,登录等等,然后可以通过request.getPathInfo()如上面的例子。

当你使用后缀模式,如* .do,* .html等,然后你可以调用像http://example.com/register.do,http://example.com/login.do等的URL,你应该更改这个答案(也是ActionFactory)中的代码示例提取寄存器和登录零件由request.getServletPath()。

Action应该遵循Strategy pattern.它需要被定义为一个抽象/接口类型,它应该基于抽象方法的传入参数进行工作(这是与Command pattern的区别,其中抽象/接口类型应该基于在实现的创建期间传递的参数来进行工作)。

public interface Action {

public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception;

}

你可能想使异常更具体的自定义异常,如ActionException。这只是一个基本的开球的例子,其余的一切都取决于你。

这里有一个LoginAction的例子(如它的名字所示)登录用户。用户本身又是一个数据模型。视图意识到用户的存在。

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.

}

}

}

ActionFactory应该遵循Factory method pattern.基本上,它应该提供一个创建方法,返回一个抽象/接口类型的具体实现。在这种情况下,它应该基于请求提供的信息返回Action接口的实现。例如,method和pathinfo(pathinfo是请求URL中上下文和servlet路径之后的部分,不包括查询字符串)。

public static Action getAction(HttpServletRequest request) {

return actions.get(request.getMethod() + request.getPathInfo());

}

动作又应该是一些静态/应用范围的Map其中包含所有已知的操作。这取决于你如何填写这个地图。硬编码:

actions.put("POST/register", new RegisterAction());

actions.put("POST/login", new LoginAction());

actions.put("GET/logout", new LogoutAction());

// ...

或者基于类路径中的属性/ XML配置文件进行配置:(pseudo)

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());

}

}

请记住,为没有映射的情况创建一个“无操作”操作。让它例如直接返回request.getPathInfo()。substring(1)then。

其他图案

这些是迄今为止的重要模式。

为了更进一步,您可以使用Facade pattern创建一个Context类,它依次包装请求和响应对象,并提供一些方便的方法委托给请求和响应对象,并将其作为参数传递到Action#execute()方法代替。这增加了一个额外的抽象层来隐藏原始的Servlet API。你应该基本上最终在每个Action实现中导入javax.servlet。*声明。在JSF术语中,这是FacesContext和ExternalContext类正在做的。你可以在this answer找到一个具体的例子。

然后有State pattern的情况下,你想添加一个额外的抽象层来分割收集请求参数,转换,验证它们,更新模型值和执行操作的任务。在JSF术语中,这是LifeCycle正在做的。

然后是Composite pattern的情况下,你想创建一个基于组件的视图,可以附加到模型,其行为取决于基于请求的生命周期的状态。在JSF术语中,这是UIComponent代表的。

这种方式可以逐位演进到基于组件的框架。

也可以看看:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值