jw的github地址是https://github.com/menyouping/jw
第一次看到这篇文章时非常惊讶,介绍FastPHP如何实现一个简易的MVC。我的大脑中总是将Servlet与Spring MVC割裂开来,总认为是两个事物,看到这篇文章后茅塞顿开!Java版的MVC,我也可以玩了!
理一下思路:当外界发送一个请求,被jw-web拦截,请求跳转到一个自定义的HttpServlet中,Servlet解析请求地址再将请求转到相应的Controller类中,Controller类的相应函数进行逻辑处理后返回响应内容,这样MVC逻辑就走完了,是不是感觉有点简单,用Java反射功能就能实现。
下面我们一步步去完成这个MVC。
在modules节点下面添加兄弟节点,统一管理整个项目依赖的外部资源版本信息
<dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>2.5version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.7.2version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.16version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>3.8.1version>
<scope>testscope>
dependency>
dependencies>
dependencyManagement>
添加依赖
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<scope>testscope>
dependency>
dependencies>
添加依赖
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
dependency>
修改jw-web/src/main/webapp/WEB-INF/web.xml,在其中注册servlet, 拦截jw-web应用下的所有请求
<servlet>
<servlet-name>appServletservlet-name>
<servlet-class>com.jw.web.servlet.DispatcherServletservlet-class>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>appServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
新建文件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 result = new HashMap();
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);
}
}
新增类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 result = new HashMap();
result.put("status", 200);
result.put("message", "index method is invorked!");
return result;
}
public Object welcome(HttpServletRequest request, HttpServletResponse response) {
Map result = new HashMap();
result.put("status", 200);
result.put("message", "Welcome to jw's world!");
return result;
}
}
这一步不介绍了
检查一下Project Facets设置,Dynamic Web Module必须是2.5。若当前设置是2.3,打开文件jw-web/.settings/org.eclipse.wst.common.project.facet.core.xml
,修改jst.web和java的jdk版本,可参考此文。
<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,右键Debug As -> Debug on Server
服务器启动,打开了http://localhost:8080/jw-web/ ,显示如下
Hello World!
显示内容来自于jw-web/src/main/webapp/index.jsp
修改网址,http://localhost:8080/jw-web/index.jsp,回车。
页面仍显示:
Hello World!
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