自己实现一个简易的SpringMVC

来源:互联网 发布:2017网络综艺节目 编辑:程序博客网 时间:2024/04/29 20:36

上回实现了一个简易的Spring,那就顺便实现一些SpringMVC吧。由于有了上回的基础,这回实现比较快,晚饭前架构了一下,一晚上就写得差不多了。自己实现的架构比较简单,下面简单介绍一下。

源码下载:http://download.csdn.net/detail/jobsandczj/9844308

实现思路及工作流程

定义一个DispatcherServlet,用来做请求入口。初始化时,去读取配置文件,获得Controller的包,然后“注入”Controller。SpringMVC它本身是有自己的IoC容器的,用来注入Controller以及它的组件,但IoC我在Spring里玩过了,这回就没有写依赖注入。但完事后发现其实也没省多少功夫,终归还是要扫包,解析的。

得到Controller后就构建Handler。让每个Handler与一个请求路径对应,我只定义了两种类型的Handler,一个是处理页面转发的,一个是返回Json数据的。每种Handler都有它的适配器,这就让Controller的方法设置参数少了很多约束,只要是request,response,session这仨家伙就行。

最后初始化适配器列表,以便在接收到请求后适配。


下面是Handler抽象类:

package MySpringMVC.springmvc;import java.lang.reflect.Method;/** * Created by 10033 on 2017/5/16. */public abstract class Handler {    protected Method method;    protected Object controller;    protected Class[] params;    protected RequestMethod requestMethod;    public Handler(Method method, Object controller, Class[] params, RequestMethod requestMethod) {        this.method = method;        this.controller = controller;        this.params = params;        this.requestMethod = requestMethod;    }    public Method getMethod() {        return method;    }    public void setMethod(Method method) {        this.method = method;    }    public Object getController() {        return controller;    }    public void setController(Object controller) {        this.controller = controller;    }    public Class[] getParams() {        return params;    }    public void setParams(Class[] params) {        this.params = params;    }    public RequestMethod getRequestMethod() {        return requestMethod;    }    public void setRequestMethod(RequestMethod requestMethod) {        this.requestMethod = requestMethod;    }}

下面这个是操作工具类,进行方法参数适配和适配器列表初始化

package MySpringMVC.utils;import MySpringMVC.springmvc.ClasspathPackageScanner;import MySpringMVC.springmvc.HandlerAdapter;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;import java.util.List;/** * Created by 10033 on 2017/5/16. */public class OperationUtil {    private static final Logger logger = LoggerFactory.getLogger(OperationUtil.class);    private static final String ADAPTER_PACKAGE="MySpringMVC.springmvc";    public static int makeObjectsByClasses            (Class[] classes, Object[] objects, HttpServletRequest request, HttpServletResponse response) throws Exception {        int cou=0;        for(Class cla:classes) {            if(cla==HttpServletRequest.class) {                objects[cou++]=request;            } else if(cla==HttpServletResponse.class) {                objects[cou++]=response;            } else if(cla==HttpSession.class) {                objects[cou++]=request.getSession();            } else {                throw new Exception("控制器参数错误");            }        }        return cou;    }    public static void initHandlerAdapterList(List<HandlerAdapter> list) {        try {            List<String> classStringList=new ClasspathPackageScanner(ADAPTER_PACKAGE).getFullyQualifiedClassNameList();            for(String s:classStringList) {                Class cla=Class.forName(s);                //实现了HandlerAdapter接口                if (HandlerAdapter.class.isAssignableFrom(cla)) {                    Object obj=cla.newInstance();                    list.add((HandlerAdapter) obj);                }            }        } catch (IOException e) {            logger.error(e.getMessage());        } catch (ClassNotFoundException e) {            logger.error(e.getMessage());        } catch (IllegalAccessException e) {            logger.error(e.getMessage());        } catch (InstantiationException e) {            logger.error(e.getMessage());        }    }}
这是DispatcherServlet类,进行初始化和控制器调度,为了管理静态资源要进行servlet注册。

package MySpringMVC.springmvc;import MySpringMVC.utils.OperationUtil;import MySpringMVC.utils.PropertiesReaderUtil;import MySpringMVC.utils.StringUtil;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.servlet.ServletConfig;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.ServletRegistration;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.util.ArrayList;import java.util.List;import java.util.Map;/** * Created by 10033 on 2017/5/16. */public class DispatcherServlet extends HttpServlet {    private static final Logger logger = LoggerFactory.getLogger(DispatcherServlet.class);    private String configName;    private Map<String, String> configMap;    private static final String SCAN_PACK="scan.package";    private static final String VIEWPATH_STATIC="viewpath.static";    private HandlerMap handleMap;    private List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();    //初始化    public void init(String configName) throws ServletException {        super.init();//        configName=getInitParameter("contextConfigLocationName");        configMap= PropertiesReaderUtil.getProperties(configName);        String packages=configMap.get(SCAN_PACK);//获得扫描包        DispatchHelper.setMap(configMap);        try {            List<String> list=new ClasspathPackageScanner(packages).getFullyQualifiedClassNameList();            handleMap=new HandlerMap(list);        } catch (IOException e) {            logger.error(e.getMessage());        }        OperationUtil.initHandlerAdapterList(handlerAdapters);    }    @Override    public void init(ServletConfig config) throws ServletException {        init(config.getInitParameter("contextConfigLocationName"));        ServletContext servletContext=config.getServletContext();        /*ServletRegistration servletRegistration = servletContext.getServletRegistration("jsp");        servletRegistration.addMapping("/WEB-INF/jsps*//*");*/        ServletRegistration servletRegistration2 = servletContext.getServletRegistration("default");        String[] staticString=configMap.get(VIEWPATH_STATIC).split(";");        for(int i=0;i<staticString.length;i++) {            servletRegistration2.addMapping(staticString[i].toLowerCase()+"/*");        }    }    @Override    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        //获取请求路径        String requestUrl=StringUtil.getRequestURL(req);        Handler handler=handleMap.getHandler(requestUrl,req.getMethod());        if(null!=handler) {            for(HandlerAdapter handlerAdapter:handlerAdapters) {                if(handlerAdapter.support(handler)) {                    handlerAdapter.setHandler(handler);                    handlerAdapter.execute(req,resp);                    break;                }            }        }else {            resp.sendError(HttpServletResponse.SC_NOT_FOUND);        }    }}

这回还是有一些不足的,一是没实现IoC,当然这是自己偷懒。但还有一个不足就是,由于前端只支持JSP,所以View,Model这些也都没管。