相信从事web开发的java开发人员都用过mvc框架如struts、springMVC等。你是否好奇他们的实现原理呢?大家也许知道他们的原理,并也写过类似的mvc框架,如果你已经懂其原理可以直接pass掉这篇文章,如果你还未了解又有兴趣的话,不妨进来看看。接下来进入正文。
我的示例访问路径为: http://localhost:8080/StrutsDemo/hello/sayHello.do
1.不管是struts还是springMVC他们最基本的实现原理都是抓取每一次请求的9大对象,将其赋值到自定义类中,再在自定义类中获取相应的参数和输出开发人员欲输出的信息。
以下是我的自定义类
/**
* 自定义类,功能类似于servlet,用于抓取java web 9大对象,
* 此处示例只抓取了request和response对象,然后通过request和response对象
* 作相应的页面跳转、响应json、传递参数等操作。
*
* !!!!!设置页面跳转参数等这些方法此处没有实现,实现方式和传统的serlvet一样。
* @author gd_xbb
*
*/
public abstract class Controller {
private HttpServletRequest request;
private HttpServletResponse response;
/**
* 响应json
* @param target
*/
public void responseJson(Object target){
try {
PrintWriter out = getResponse().getWriter();
out.print(JSON.toJSONString(target));
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 客户端跳转
* @param path
*/
public void redirect(String path){
try {
response.sendRedirect(request.getContextPath() + path);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取request对象
* @return
*/
public HttpServletRequest getRequest() {
return request;
}
/**
* 设置request对象
* @param request
*/
public void setRequest(HttpServletRequest request) {
this.request = request;
}
/**
* 获取response对象
* @return
*/
public HttpServletResponse getResponse() {
return response;
}
/**
* 设置response对象
* @param response
*/
public void setResponse(HttpServletResponse response) {
this.response = response;
}
}
2.接下来我们要定义自己的路由信息以下是我的实现:
public class ControllerConfig {
public static Map<String, Class<? extends Controller>> router = new HashMap<String, Class<? extends Controller>>();
static {
router.put("hello", HelloController.class);
}
}
这路由的定义主要是为了一会儿反射生成Controller对象
3.实现我们自已的mvc框架的过滤器或者servlet作为框架的统一入口。我用的是过滤器。以下是我的代码:
/**
* 仿struts过滤器,统一入口
* @author gd_xbb
*
*/
public class StrutsFilter implements Filter{
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest svltReq, ServletResponse svltRes, FilterChain fltChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) svltReq;
HttpServletResponse response = (HttpServletResponse) svltRes;
String requestUrl = request.getRequestURI();
String[] reflectInfo = getReflectInfo(requestUrl, request.getContextPath());
String classKey = reflectInfo[0];
String methodName = reflectInfo[1];
executeTarget(classKey, methodName, request, response);
return;
}
/**
* 执行目标方法
* @param classKey路由中Controller对应的Key
* @param methodName对应请求的Controller的方法
* @param requestrequest对象
* @param responseresponse对象
*/
private void executeTarget(String classKey, String methodName, HttpServletRequest request, HttpServletResponse response){
try {
Controller controller= ControllerConfig.router.get(classKey).newInstance();
controller.setRequest(request); controller.setResponse(response);
Method method = controller.getClass().getMethod(methodName);
method.invoke(controller);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 得到反射的信息
* @param requestUrl请求路径
* @param contextPathweb项目的contextPath
* @return
*/
private String[] getReflectInfo(String requestUrl, String contextPath){
int contextPathLastIndex = requestUrl.indexOf(contextPath) + contextPath.length();
String reflectInfo = requestUrl.substring(contextPathLastIndex);
reflectInfo = reflectInfo.replaceFirst(".do", "").replaceFirst("/", "");
String methodName = reflectInfo.substring(reflectInfo.lastIndexOf("/") + 1);
String classKey = reflectInfo.substring(0, reflectInfo.lastIndexOf("/"));
String[] reflectArray = {classKey, methodName};
return reflectArray;
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
在web.xml中配置好我们的filter
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>StrutsDemo</display-name>
<filter>
<filter-name>struts</filter-name>
<filter-class>com.gzykdx.strutsDemo.interceptor.StrutsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
</web-app>
以上代码的核心思想:通过路径中的hello查询路由反射生成HelloController对象,并调用HelloController中的sayHello方法
4.实现我们自己的Controller类。代码:
public class HelloController extends Controller {
public void sayHello() throws IOException{
responseJson("Hello world");
}
}
以上就是一个仿mvc框架的核心实现。 本人因为技术和时间原因写得不好,请各位大神留情。^*(- -)*^
以下是源代码下载地址:https://github.com/xbb0220/HowStrutsImplemented
demo的访问地址: http://localhost:8080/StrutsDemo/hello/sayHello.do