写了个最简单的最粗糙的mvc的架构。
在web的xml中配置过滤器以及在页面上显示的标签。
<filter>
<filter-name>bushyou</filter-name>
<filter-class>com.bushyou.servlet.dispatcher.FilterDispatcher</filter-class>
</filter>
<!-- Extension -->
<filter-mapping>
<filter-name>bushyou</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
<jsp-config>
<taglib>
<taglib-uri>/bushyou</taglib-uri>
<taglib-location>/WEB-INF/bushyou.tld</taglib-location>
</taglib>
</jsp-config>
将web的含有.html的请求都经过FilterDispatcher这个过滤器。
在FilterDispatcher中。
/**
* 拦截请求
*
* @author shanzhu
* @version 1.0 2011-9-29
*/
package com.bushyou.servlet.dispatcher;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.bushyou.action.IAction;
import com.bushyou.servlet.context.ActionMapper;
import com.bushyou.servlet.context.ListBushyouActionMapper;
import com.bushyou.servlet.context.ValueContext;
public class FilterDispatcher implements Filter {
private FilterConfig filterConfig;
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain arg2) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
ServletContext servletContext = getServletContext();
//将request,response,servletContext放入值域中。
ValueContext valueContext = new ValueContext(request, response,
servletContext);
//将值域放入request对象中。
request.setAttribute("bushyou_value_context", valueContext);
//返回的jsp页面。mvc中的 v
String pa = "";
if (ListBushyouActionMapper.map.containsKey(valueContext.getPath())) {
ActionMapper actionMapper = ListBushyouActionMapper.map.get(valueContext.getPath());
valueContext.setActionMapper(actionMapper);
IAction action = null;
String returnStr = null;
try {
//反射出acion对象。
Class classType = Class.forName(valueContext.getActionMapper().getClassPath());
//执行构造函数。
Constructor constructor = classType.getConstructor();
action = (IAction) constructor.newInstance();
//执行excuse方法。得到返回值。
returnStr = action.excute();
} catch (ClassNotFoundException e) {
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
} catch (IllegalArgumentException e) {
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
//将action对象放入值域中。
valueContext.setAction(action);
pa = valueContext.getActionMapper().getReturnUrl();
}
//forward
RequestDispatcher requestDispatcher = request
.getRequestDispatcher(pa);
requestDispatcher.forward(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
protected ServletContext getServletContext() {
return filterConfig.getServletContext();
}
}
在上面的代码中。我们已经将整个mvc的过程走完了。
当请求经过这个过滤器的时候,过滤器想将值域放入request对象,然后反射出action对象。执行提供出去的excuse方法。
/**
* 值栈
*
* @author shanzhu
* @version 1.0 2011-9-29
*/
package com.bushyou.servlet.context;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.bushyou.action.IAction;
public class ValueContext {
ValueMap valueMap; //值域,放入的request,response,servletContext,action执行后 对象
ActionMapper actionMapper ; //action对象
List extensions = new ArrayList() {{ add("html");}};
IAction action;
String path;
public ValueContext(HttpServletRequest request,
HttpServletResponse response, ServletContext servletContext) {
valueMap = new ValueMap();
valueMap.setRequest(request);
valueMap.setResponse(response);
valueMap.setServletContext(servletContext);
String path = getServletPath(request);
this.path = path;
path = dropExtension(path);
parseNameAndNamespace(path);
}
/**
* 拿到请求的url
* @param request
* @return
*/
public static String getServletPath(HttpServletRequest request) {
String servletPath = request.getServletPath();
if (null != servletPath && !"".equals(servletPath)) {
return servletPath;
}
String requestUri = request.getRequestURI();
int startIndex = request.getContextPath().equals("") ? 0 : request.getContextPath().length();
int endIndex = request.getPathInfo() == null ? requestUri.length() : requestUri.lastIndexOf(request.getPathInfo());
if (startIndex > endIndex) { // this should not happen
endIndex = startIndex;
}
return requestUri.substring(startIndex, endIndex);
}
String dropExtension(String name) {
if (extensions == null) {
return name;
}
Iterator it = extensions.iterator();
while (it.hasNext()) {
String extension = "." + (String) it.next();
if (name.endsWith(extension)) {
name = name.substring(0, name.length() - extension.length());
return name;
}
}
return name;
}
/**
* 解析成 actionMapper对象。
* @param uri
*/
void parseNameAndNamespace(String uri) {
String namespace, name;
int lastSlash = uri.lastIndexOf("/");
if (lastSlash == -1) {
namespace = "";
name = uri;
} else if (lastSlash == 0) {
// ww-1046, assume it is the root namespace, it will fallback to
// default
// namespace anyway if not found in root namespace.
namespace = "/";
name = uri.substring(lastSlash + 1);
}else {
namespace = uri.substring(0, lastSlash);
name = uri.substring(lastSlash + 1);
}
if (name != null) {
int pos = name.lastIndexOf('/');
if (pos > -1 && pos < name.length() - 1) {
name = name.substring(pos + 1);
}
}
actionMapper = new ActionMapper();
actionMapper.setActionName(name);
actionMapper.setNamespace(namespace);
}
public Map getValueMap() {
return valueMap;
}
public IAction getAction() {
return action;
}
public void setAction(IAction action) {
this.valueMap.setAction(action);
this.action = action;
}
public ActionMapper getActionMapper() {
return actionMapper;
}
public void setActionMapper(ActionMapper actionMapper) {
this.actionMapper = actionMapper;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
上面是放入的值域。主要是用在前台的jsp标签使用。
/**
* property 标签,用于显示属性。
*
* @author shanzhu
* @version 1.0 2011-9-29
*/
package com.bushyou.servlet.tag;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
import com.bushyou.servlet.context.ValueContext;
public class PropertyTag extends BodyTagSupport {
@Override
public int doEndTag() throws JspException {
HttpServletRequest request = (HttpServletRequest) pageContext
.getRequest();
ValueContext valueContext = (ValueContext) request
.getAttribute("bushyou_value_context");
Object o = valueContext.getValueMap().get(value);
// 取得标签体对象
try {
pageContext.getOut().write((String)o);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.doAfterBody();
}
private String value;
private boolean escape;
private static final long serialVersionUID = 8921307524633290358L;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public boolean isEscape() {
return escape;
}
public void setEscape(boolean escape) {
this.escape = escape;
}
}
上面是jsp的自定义标签的方法。
/**
* 继承hashmap
*
* 在页面上用于展现的时候,所有的值域都在这个容器内。
*
* 复写他的get方法
*
* @author shanzhu
* @version 1.0 2011-9-29
*/
package com.bushyou.servlet.context;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.bushyou.action.IAction;
public class ValueMap<K, V> extends HashMap<K, V> {
/**
*
*/
private static final long serialVersionUID = 4023788960770640801L;
HttpServletRequest request;
HttpServletResponse response;
ServletContext servletContext;
IAction action;
public void setRequest(HttpServletRequest request) {
this.request = request;
}
public void setResponse(HttpServletResponse response) {
this.response = response;
}
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
@Override
public V get(Object key) {
V v = null;
Class classType = action.getClass();
try {
Field field = classType.getDeclaredField((String) key);
if (!Modifier.isPublic(field.getModifiers())) {
field.setAccessible(true);
}
v = (V) field.get(action);
} catch (SecurityException e) {
} catch (NoSuchFieldException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
if (v != null) {
return v;
}
v = super.get(key);
if (v != null) {
return v;
}
v = (V) request.getAttribute(key + "");
if (v != null) {
return v;
}
return v;
}
public void setAction(IAction action) {
this.action = action;
}
}
从标签中取值的相应的类。
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>b</short-name>
<uri>http://www.koubei.com</uri>
<tag>
<name>property</name>
<tag-class>com.bushyou.servlet.tag.PropertyTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>value</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description><![CDATA[Value to be displayed]]></description>
</attribute>
<attribute>
<name>escape</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description><![CDATA[ Whether to escape HTML]]></description>
</attribute>
</tag>
</taglib>
tld文件。
现在写点测试的例子:
/**
* mvc的m的入口
*
* @author shanzhu
* @version 1.0 2011-9-29
*/
package com.bushyou.action;
import java.io.Serializable;
public interface IAction extends Serializable{
String excute();
}
/**
* hello的例子
*
* @author shanzhu
* @version 1.0 2011-9-29
*/
package com.bushyou.action;
public class YeXiaoGangHelloAction implements IAction{
/**
*
*/
private static final long serialVersionUID = -5712396283469842107L;
private String str1;
private String str2;
@Override
public String excute() {
str1 = "hello str1";
str2 = "hello str2";
return "success";
}
public String getStr1() {
return str1;
}
public void setStr1(String str1) {
this.str1 = str1;
}
public String getStr2() {
return str2;
}
public void setStr2(String str2) {
this.str2 = str2;
}
}
/**
* test的例子
*
* @author shanzhu
* @version 1.0 2011-9-29
*/
package com.bushyou.action;
public class YeXiaoGangTestAction implements IAction{
/**
*
*/
private static final long serialVersionUID = -5712396283469842107L;
private String str1;
private String str2;
@Override
public String excute() {
str1 = "test str1";
str2 = "test str2";
return "success";
}
public String getStr1() {
return str1;
}
public void setStr1(String str1) {
this.str1 = str1;
}
public String getStr2() {
return str2;
}
public void setStr2(String str2) {
this.str2 = str2;
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@taglib prefix="b" uri="/bushyou" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>First HelloWorldServlet</title>
</head>
<body>
11
<br />
<b:property value="str1"></b:property>
<br />
22222
<br />
<b:property value="str2"></b:property>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@taglib prefix="b" uri="/bushyou" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>test</title>
</head>
<body>
<b:property value="str1"></b:property>
||
<b:property value="str2"></b:property>
</body>
</html>
在浏览器上输入http://localhost/testweb/yexiaogang/hello.html
http://localhost/testweb/yexiaogang/test.html
就可以看到效果了。