Servlet之动作框架

408 阅读3分钟
原文链接: blog.zhengsj.top

参考: Java Servlet 技术简介

概述

动作框架,是指编写一个Servlet(请求入口),解析请求的URI得到动作名称,调用处理用户请求的动作类,完成请求访问。当动作执行完毕后,返回一个指向表示结果的JSP的URL(也可以用模板引擎)。
学习过MVC的同学可以在这里一一对应。Servlet通过调用ActionFactory起到路由的作用,处理用户的动作类即是Controller,Controller会调用Model完成任务处理,处理完毕后,返回的URI指向的JSP就是用于表示的View。

大致框架图如下:
框架图

详述

在这,会具体把实现动作框架所需部件的功能及构成详细叙述一遍,已达到每一部分都尽量清楚的目的。

Servlet

“唯一”的Servlet。所有请求的入口,继承自HttpServlet,解析出动作名称,然后通过动作工厂ActionFactory得到具体的动作对象,执行动作的perform方法,最后转发请求到返回的URL。
示例:

package com.example;

import java.io.IOException;
import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.example.actions.Action;

public class actionServlet extends HttpServlet {
	private ActionFactory factory = ActionFactory.getSingleton();
    
    // public void init(ServletConfig config) throws ServletException { ... }
	
    public void service(HttpServletRequest req, HttpServletResponse res) 
    		throws ServletException, IOException {
    	// 获得动作的名称
        String actionName = getActionName(req);
        // 通过动作工厂生成actionName的实例对象
        Action action = factory.create(actionName);
        // 执行动作,得到返回的URL
        String url = action.perform(req, res);
		// 通过url显示结果
		if (url != null)
        	getServletContext().getRequestDispatcher(url).forward(req, res);
    }
    
    // public void destroy() { ... }
    
    private String getActionName(HttpServletRequest req) {
    	String path = req.getServletPath();
        return path.substring(path.lastIndexOf('/'),  path.lastIndexOf('.'));
    }
}

ActionFactory

记录所有动作,通过Servlet发出的动作名称得到动作类,然后对该类实例化,并返回实例对象。
起到存储所有动作、查找指定动作的目的。
示例:

package com.example;

import com.example.actions.*;

import java.util.HashMap;
import java.util.Map;

public class ActionFactory {
	private Map actionsMap = defaultMap();
    private static ActionFactory singleton;
    
    public static ActionFactory getSingleton() {
    	if (singleton == null)
        	singleton = new ActionFactory();
        return singleton;
    }
    
    public Action create(String actionName) {
    	Class klass = (Class)map.get(actionName);
        if (klass == null) {
        	throw new RuntimeException(getClass() + " was unable to find an action named '" + actionName + "'.");
        }
        Action actionInstance = null;
        try {
        	actionInstance = (Action)kalss.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return actionInstance;
    }
    
    private Map defaultMap() {
        Map map = new HashMap();
        
        map.put("example1", example1Action.class);
        map.put("example2", example2Action.class);
        // ...
        
        return map;
 }

Action

动作类,继承Action接口,完成请求的各项动作。通过调用其他类来完成请求任务,并返回显示结果的jsp的URL。
Action接口

package com.example.actions;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public interface Action {
	public String perform(HttpServletRequest request, HttpServletResponse response);
}

示例:

package com.example.actions;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// import ...

public class exampleAction implements Action {
	@Override
    public String perform(HttpServletRequest req, HttpServletResponse res) {
    	// do something ...
        return "/example.jsp"
    }
}

web.xml

配置当某类url到达服务器时,执行哪个servlet。比如,在这里,我们把所有以.perform为后缀的url都用咱们前面创建的com.example.exampleServlet来处理。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
						 "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
    <servlet>
        <servlet-name>example</servlet-name>
        <servlet-class>com.example.exampleServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>example</servlet-name>
        <url-pattern>*.perform</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>example</servlet-name>
        <url-pattern>index.html</url-pattern>
    </servlet-mapping>
</web-app>

体会

  • 通过动作框架,可以只编写一个的Servlet来总括系统的构建,这个Servlet为入口,解析url,通过ActionFactory得到动作,然后开始执行动作,最后返回显示结果,就完成了简单的请求访问。
  • 在构建过程中,要对动作的编写分门别类,以达到清晰明了、易于维护的目的。
  • 业务与逻辑不混合原则。专注于逻辑的实现,但不是用servlet来实现,而是用单纯的java来实现,servlet直接或间接的调用。

题外话

  • 文章开头的参考文章写的很好,有一个具体的Demo,请大家一定去看看。
  • 糙汉子,写的不好不对的地方还请您能够予以指正,感激。
  • 记得用IDE,刚开始想用Sublime来试一试,最后崩了。大神请无视。