欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

serlvet的mvc架构最简版 servletjavafiltermvc 

程序员文章站 2022-07-02 13:33:18
...
   写了个最简单的最粗糙的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
就可以看到效果了。