3.自己动手写Java Web框架-MVC初体验

来源:互联网 发布:python library api 编辑:程序博客网 时间:2024/05/22 23:36

jw的github地址是https://github.com/menyouping/jw

第一次看到这篇文章时非常惊讶,介绍FastPHP如何实现一个简易的MVC。我的大脑中总是将Servlet与Spring MVC割裂开来,总认为是两个事物,看到这篇文章后茅塞顿开!Java版的MVC,我也可以玩了!

理一下思路:当外界发送一个请求,被jw-web拦截,请求跳转到一个自定义的HttpServlet中,Servlet解析请求地址再将请求转到相应的Controller类中,Controller类的相应函数进行逻辑处理后返回响应内容,这样MVC逻辑就走完了,是不是感觉有点简单,用Java反射功能就能实现。

下面我们一步步去完成这个MVC。

添加依赖

修改jw-parent/pom.xml

在modules节点下面添加兄弟节点,统一管理整个项目依赖的外部资源版本信息

<dependencyManagement>    <dependencies>        <dependency>            <groupId>javax.servlet</groupId>            <artifactId>servlet-api</artifactId>            <version>2.5</version>        </dependency>        <dependency>            <groupId>org.slf4j</groupId>            <artifactId>slf4j-log4j12</artifactId>            <version>1.7.2</version>        </dependency>        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>fastjson</artifactId>            <version>1.2.16</version>        </dependency>        <dependency>            <groupId>junit</groupId>            <artifactId>junit</artifactId>            <version>3.8.1</version>            <scope>test</scope>        </dependency>    </dependencies></dependencyManagement>

修改jw-core/pom.xml

添加依赖

<dependencies>    <dependency>        <groupId>javax.servlet</groupId>        <artifactId>servlet-api</artifactId>    </dependency>    <dependency>        <groupId>org.slf4j</groupId>        <artifactId>slf4j-log4j12</artifactId>    </dependency>    <dependency>        <groupId>com.alibaba</groupId>        <artifactId>fastjson</artifactId>    </dependency>    <dependency>        <groupId>junit</groupId>        <artifactId>junit</artifactId>        <scope>test</scope>    </dependency></dependencies>

修改jw-web/pom.xml

添加依赖

<dependency>    <groupId>javax.servlet</groupId>    <artifactId>servlet-api</artifactId></dependency><dependency>    <groupId>org.slf4j</groupId>    <artifactId>slf4j-log4j12</artifactId></dependency><dependency>    <groupId>com.alibaba</groupId>    <artifactId>fastjson</artifactId></dependency>

修改web.xml

修改jw-web/src/main/webapp/WEB-INF/web.xml,在其中注册servlet, 拦截jw-web应用下的所有请求

<servlet>    <servlet-name>appServlet</servlet-name>    <servlet-class>com.jw.web.servlet.DispatcherServlet</servlet-class>    <load-on-startup>1</load-on-startup></servlet><servlet-mapping>    <servlet-name>appServlet</servlet-name>    <url-pattern>/</url-pattern></servlet-mapping>

创建Servlet

新建文件jw-core/src/main/java/com/jw/web/servlet/DispatcherServlet.java

package com.jw.web.servlet;import java.io.IOException;import java.lang.reflect.Method;import java.util.HashMap;import java.util.Map;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.alibaba.fastjson.JSON;import com.jw.util.ConfigUtils;import com.jw.util.StringUtils;public class DispatcherServlet extends HttpServlet {    private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class);    private static final long serialVersionUID = -3874308705324703315L;    public DispatcherServlet() {    }    public void init() {    }    public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {        String appName = request.getSession().getServletContext().getContextPath();        String path = request.getRequestURI().substring(appName.length());        LOGGER.info("Request path is {}", path);        // /index/index/ => /index/index        if (path.length() > 1 && path.endsWith("/")) {            path = path.substring(0, path.length() - 1);        } else if (path.startsWith("/")) {// /index/index => index/index            path = path.replaceFirst("/", "");        }        if (path.isEmpty()) {            path = "index/index";        } else if (!path.contains("/")) {            path += "/index";// index => index/index        }        String[] paths = path.split("/", 2);        String controllerClazeName = ConfigUtils.getProperty("package.scan") + "." + StringUtils.upperFirst(paths[0])                + "Controller";        String methodName = paths[1];        try {            Class<?> controllerClaze = Class.forName(controllerClazeName);            Method method = controllerClaze.getMethod(methodName,                    new Class<?>[] { HttpServletRequest.class, HttpServletResponse.class });            Object controller = controllerClaze.newInstance();            Object result = method.invoke(controller, new Object[] { request, response });            response.setHeader("Content-type", "application/json;charset=UTF-8");            response.getWriter().write(JSON.toJSONString(result));        } catch (Exception e) {            LOGGER.error("Error raised in DispatcherServlet.", e);            Map<String, Object> result = new HashMap<String, Object>();            result.put("status", 500);            result.put("message", e.getMessage());            response.setHeader("Content-type", "application/json;charset=UTF-8");            response.getWriter().write(JSON.toJSONString(result));        }    }}

controllerClazeName由两部分组成,第一部分ConfigUtils.getProperty(“package.scan”)是package的路径,第二部分是Controller的类名StringUtils.upperFirst(paths[0]) + “Controller”, StringUtils.upperFirst()使首字母大写。

添加配置文件jw-web/src/main/resources/application.properties

package.scan=com.jay.mvc

package.scan配置了Controller类所在的package地址。

新增类jw-core/src/main/java/com/jw/util/StringUtils.java

package com.jw.util;public class StringUtils {    public static boolean isEmpty(String str) {        return str == null || str.isEmpty();    }    /**     * 首字母大写     *      * @param str     * @return     */    public static String upperFirst(String str) {        if (StringUtils.isEmpty(str))            return str;        char ch = str.charAt(0);        if (ch < 'a' || ch > 'z')            return str;        char[] cs = str.toCharArray();        cs[0] = Character.toUpperCase(ch);        return String.valueOf(cs);    }}

测试

添加测试Controller

新增类jw-web/src/main/java/com/jay/mvc/IndexController.java

package com.jay.mvc;import java.util.HashMap;import java.util.Map;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class IndexController {    public Object index(HttpServletRequest request, HttpServletResponse response) {        Map<String, Object> result = new HashMap<String, Object>();        result.put("status", 200);        result.put("message", "index method is invorked!");        return result;    }    public Object welcome(HttpServletRequest request, HttpServletResponse response) {        Map<String, Object> result = new HashMap<String, Object>();        result.put("status", 200);        result.put("message", "Welcome to jw's world!");        return result;    }}

添加Tomcat7 server

这一步不介绍了

修改Project Facets

检查一下Project Facets设置,Dynamic Web Module必须是2.5。若当前设置是2.3,打开文件jw-web/.settings/org.eclipse.wst.common.project.facet.core.xml
,修改jst.web和java的jdk版本,可参考此文。

<?xml version="1.0" encoding="UTF-8"?><faceted-project>  <fixed facet="wst.jsdt.web"/>  <installed facet="jst.web" version="2.5"/>  <installed facet="wst.jsdt.web" version="1.0"/>  <installed facet="java" version="1.7"/></faceted-project>

消除错误

如果在Problem面板中看到xx/target/classes/META-INF/MANIFES no such file or directory的错误,依次点击菜单Window/Preference/Maven/Java EE Intergration, 不勾选Maven Archiver generates files under the build directory。

启动jw-web

选中jw-web,右键Debug As -> Debug on Server
服务器启动,打开了http://localhost:8080/jw-web/ ,显示如下

Hello World!

显示内容来自于jw-web/src/main/webapp/index.jsp

测试jsp

修改网址,http://localhost:8080/jw-web/index.jsp,回车。
页面仍显示:

Hello World!

测试MVC

MVC的地址规则是http://localhost:8080/jw-web/{{controller}}//{{method}}
,{{method}}不填时默认为index方法。
修改网址,http://localhost:8080/jw-web/index ,回车。
调试时可以看到controllerClazeName的运行时值是”com.jay.mvc.IndexController”,成功找到目标Controller.
method的值是”com.jay.mvc.IndexController.index(HttpServletRequest,HttpServletResponse)”, 目标方法也找到。
最后看到页面显示:

{"message":"index method is invorked!","status":200}

修改网址,http://localhost:8080/jw-web/welcome,回车。
页面显示:

{"message":"com.jay.mvc.WelcomeController","status":500}

出错了,因为没有找到WelcomeController。

修改网址,http://localhost:8080/jw-web/index/welcome,回车。
页面显示:

{"message":"Welcome to jw's world!","status":200}

至此简单的MVC完成。

本节资源地址: https://github.com/menyouping/jw-example/blob/master/3/jw-parent.zip

0 0
原创粉丝点击