基于URL的契约式简易MVC框架

一直以来对0配置的mvc框架很感兴趣。

最近,突发奇想,想试验一下如何利用url来实现契约式的mvc零配置框架。

首先,我们以一个普通的url为例。

"http://ipaddress:prot/project_name/business_name/moudle_name/action_name/"

我们假定从business_name开始我们对应的是java中的类包,moudle_name我们对应成 相应业务的对象名称。

而action_name则是 这个对象中的方法名称。

上面是我们假定的规则。

然后我们可以通过reflect可以找到这个请求相关的方法。这样就可以不同过配置文件来配置相关信息。

同事,我们在定义相对应的annotation来为操作成功失败后做跳转。

以上就是一个大概的思路。现在给大家看看相应的代码。

 

 

首先是我们的web。xml文件

Xml代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.4"    
  3.     xmlns="http://java.sun.com/xml/ns/j2ee"    
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee    
  6.     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  
  7.     <servlet>  
  8.     <servlet-name>action</servlet-name>  
  9.     <servlet-class>com.pig.hub.dev.frameWork.action.ActionServlet</servlet-class>  
  10.     <init-param>  
  11.     <param-name>filename</param-name>  
  12.     <param-value>pig.web</param-value>  
  13.     </init-param>  
  14.      <load-on-startup>0</load-on-startup>  
  15.   </servlet>  
  16.   <servlet-mapping>  
  17.     <servlet-name>action</servlet-name>  
  18.     <url-pattern>*.pig</url-pattern>  
  19.   </servlet-mapping>  
  20.   <welcome-file-list>  
  21.     <welcome-file>index.jsp</welcome-file>  
  22.   </welcome-file-list>  
  23. </web-app>  
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
	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-app_2_4.xsd">
	<servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>com.pig.hub.dev.frameWork.action.ActionServlet</servlet-class>
    <init-param>
    <param-name>filename</param-name>
    <param-value>pig.web</param-value>
    </init-param>
     <load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.pig</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 其中定义了com.pig.hub.dev.frameWork.action.ActionServlet来去拦截所有的请求(。pig)。filename这个属性是为了给出系统中相应的完成的包名。

 

下面是ActionServlet相应的java代码

Java代码 复制代码
  1. import com.pig.hub.dev.frameWork.action.exception.MakeUriException;   
  2.   
  3. /**  
  4.  * @author   
  5.  */  
  6. public abstract class AbActionServlet extends HttpServlet implements  
  7.         BasicActionServlet {   
  8.   
  9.     /**  
  10.      *   
  11.      */  
  12.     private static final long serialVersionUID = 7911661010594064823L;   
  13.   
  14.     public void doGet(HttpServletRequest request, HttpServletResponse response)   
  15.             throws ServletException, IOException {   
  16.         try {   
  17.             doWork(request, response);   
  18.         } catch (MakeUriException e) {   
  19.         }   
  20.     }   
  21.   
  22.     public void doPost(HttpServletRequest request, HttpServletResponse response)   
  23.             throws ServletException, IOException {   
  24.         try {   
  25.             doWork(request, response);   
  26.         } catch (MakeUriException e) {   
  27.         }   
  28.     }   
  29.   
  30.     /**  
  31.      * @param request  
  32.      * @param response  
  33.      * @throws ServletException  
  34.      * @throws IOException  
  35.      * @see com.pig.hub.dev.frameWork.action.BasicActionServlet#doWork(javax.servlet.http.HttpServletRequest,  
  36.      *      javax.servlet.http.HttpServletResponse)  
  37.      */  
  38.     public abstract void doWork(HttpServletRequest request,   
  39.             HttpServletResponse response) throws ServletException, IOException,   
  40.             MakeUriException;   
  41. }   
  42.   
  43.   
  44. ---------------------------------------------------------  
import com.pig.hub.dev.frameWork.action.exception.MakeUriException;

/**
 * @author 
 */
public abstract class AbActionServlet extends HttpServlet implements
		BasicActionServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 7911661010594064823L;

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		try {
			doWork(request, response);
		} catch (MakeUriException e) {
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		try {
			doWork(request, response);
		} catch (MakeUriException e) {
		}
	}

	/**
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 * @see com.pig.hub.dev.frameWork.action.BasicActionServlet#doWork(javax.servlet.http.HttpServletRequest,
	 *      javax.servlet.http.HttpServletResponse)
	 */
	public abstract void doWork(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException,
			MakeUriException;
}


---------------------------------------------------------
Java代码 复制代码
  1. package com.pig.hub.dev.frameWork.action;   
  2.   
  3. import java.io.IOException;   
  4.   
  5. import javax.servlet.ServletException;   
  6. import javax.servlet.http.HttpServletRequest;   
  7. import javax.servlet.http.HttpServletResponse;   
  8.   
  9. import com.pig.hub.dev.frameWork.action.exception.MakeUriException;   
  10.   
  11. /**  
  12.  *   
  13.  */  
  14. public interface BasicActionServlet {   
  15.     /**  
  16.      * @param request  
  17.      * @param response  
  18.      * @throws ServletException  
  19.      * @throws IOException  
  20.      * @throws MakeUriException  
  21.      */  
  22.     public void  doWork(HttpServletRequest request, HttpServletResponse response)   
  23.             throws ServletException, IOException,MakeUriException;   
  24. }   
  25. -------------------------------------------------------  
package com.pig.hub.dev.frameWork.action;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.pig.hub.dev.frameWork.action.exception.MakeUriException;

/**
 * 
 */
public interface BasicActionServlet {
	/**
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 * @throws MakeUriException
	 */
	public void  doWork(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException,MakeUriException;
}
-------------------------------------------------------
Java代码 复制代码
  1. package com.pig.hub.dev.frameWork.action;   
  2.   
  3. import java.io.IOException;   
  4. import java.lang.reflect.InvocationTargetException;   
  5. import java.lang.reflect.Method;   
  6. import java.util.HashMap;   
  7.   
  8. import javax.servlet.ServletException;   
  9. import javax.servlet.http.HttpServletRequest;   
  10. import javax.servlet.http.HttpServletResponse;   
  11.   
  12. import com.pig.hub.dev.frameWork.action.config.MethodBean;   
  13. import com.pig.hub.dev.frameWork.action.exception.MakeUriException;   
  14. import com.pig.hub.dev.frameWork.action.exception.MappingException;   
  15. import com.pig.hub.dev.frameWork.action.exception.MethodException;   
  16.   
  17. public class ActionServlet extends AbActionServlet implements  
  18.         BasicActionServlet {   
  19.   
  20.     /**  
  21.      *   
  22.      */  
  23.     private static final long serialVersionUID = 2848825411739564234L;   
  24.   
  25.     private String fileName;   
  26.   
  27.     public void init() throws ServletException {   
  28.         fileName = this.getInitParameter("filename");   
  29.     }   
  30.     @SuppressWarnings("unchecked")   
  31.     public void doWork(HttpServletRequest request, HttpServletResponse response)   
  32.             throws ServletException, IOException, MakeUriException {   
  33.   
  34.         String s[] = BusinessConfig.makeUri(request);   
  35.            
  36.         String errorMessage="";   
  37.         HashMap map = new HashMap();   
  38.         if (s.length > 2)   
  39.             throw new MakeUriException();   
  40.   
  41.         try {   
  42.             MethodBean mBean = BusinessConfig.makeConfig(s, fileName);   
  43.             Method m = mBean.getM();   
  44.             Class c = mBean.getC();   
  45.             m.invoke(c.newInstance(), request, response);   
  46.             map = MappingUtil.makeHashMap(m);   
  47.             request.getRequestDispatcher((String) map.get("success")).forward(   
  48.                     request, response);   
  49.   
  50.         } catch (SecurityException e) {   
  51.             errorMessage = "someting";   
  52.   
  53.         } catch (ClassNotFoundException e1) {   
  54.             errorMessage = "someting";   
  55.         } catch (MethodException e2) {   
  56.             errorMessage = "someting";   
  57.         } catch (NoSuchMethodException e3) {   
  58.             errorMessage = "someting";   
  59.         } catch (IllegalArgumentException e4) {   
  60.             errorMessage = "someting";   
  61.         } catch (IllegalAccessException e5) {   
  62.             errorMessage = "someting";   
  63.         } catch (InvocationTargetException e6) {   
  64.             errorMessage = "someting";   
  65.         } catch (InstantiationException e) {   
  66.             errorMessage = "someting";   
  67.         } catch (MappingException e) {   
  68.             errorMessage = "someting";   
  69.         } finally {   
  70.             if (!errorMessage.equals(""))   
  71.                 request.getRequestDispatcher((String) map.get("fail")).forward(   
  72.                         request, response);   
  73.                
  74.         }   
  75.     }   
  76.   
  77. }  
package com.pig.hub.dev.frameWork.action;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.pig.hub.dev.frameWork.action.config.MethodBean;
import com.pig.hub.dev.frameWork.action.exception.MakeUriException;
import com.pig.hub.dev.frameWork.action.exception.MappingException;
import com.pig.hub.dev.frameWork.action.exception.MethodException;

public class ActionServlet extends AbActionServlet implements
		BasicActionServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2848825411739564234L;

	private String fileName;

	public void init() throws ServletException {
		fileName = this.getInitParameter("filename");
	}
	@SuppressWarnings("unchecked")
	public void doWork(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException, MakeUriException {

		String s[] = BusinessConfig.makeUri(request);
		
		String errorMessage="";
		HashMap map = new HashMap();
		if (s.length > 2)
			throw new MakeUriException();

		try {
			MethodBean mBean = BusinessConfig.makeConfig(s, fileName);
			Method m = mBean.getM();
			Class c = mBean.getC();
			m.invoke(c.newInstance(), request, response);
			map = MappingUtil.makeHashMap(m);
			request.getRequestDispatcher((String) map.get("success")).forward(
					request, response);

		} catch (SecurityException e) {
			errorMessage = "someting";

		} catch (ClassNotFoundException e1) {
			errorMessage = "someting";
		} catch (MethodException e2) {
			errorMessage = "someting";
		} catch (NoSuchMethodException e3) {
			errorMessage = "someting";
		} catch (IllegalArgumentException e4) {
			errorMessage = "someting";
		} catch (IllegalAccessException e5) {
			errorMessage = "someting";
		} catch (InvocationTargetException e6) {
			errorMessage = "someting";
		} catch (InstantiationException e) {
			errorMessage = "someting";
		} catch (MappingException e) {
			errorMessage = "someting";
		} finally {
			if (!errorMessage.equals(""))
				request.getRequestDispatcher((String) map.get("fail")).forward(
						request, response);
			
		}
	}

}


以上基本有一个抽象类一个接口一个实现构成,其实只是用到了简单的模板方法。

其中,String s[] = BusinessConfig.makeUri(request);是为了得到url中相应的业务名对象名以及方法名称。

然后通过MethodBean mBean = BusinessConfig.makeConfig(s, fileName)来构建一个自定义的方法对象。

Java代码 复制代码
  1. package com.pig.hub.dev.frameWork.action.config;   
  2.   
  3. import java.lang.reflect.Method;   
  4.   
  5. import javax.servlet.http.HttpServletRequest;   
  6. import javax.servlet.http.HttpServletResponse;   
  7.   
  8. import com.pig.hub.dev.frameWork.action.exception.MethodException;   
  9.   
  10. public class MethodBean implements java.io.Serializable {   
  11.     /**  
  12.      *   
  13.      */  
  14.     private static final long serialVersionUID = -5753278542873561978L;   
  15.     private Class c;   
  16.     private Method m;   
  17.     private String name;   
  18.        
  19.   
  20.     public Class getC() {   
  21.         return c;   
  22.     }   
  23.   
  24.     public void setC(Class c) {   
  25.         this.c = c;   
  26.     }   
  27.   
  28.     public Method getM() {   
  29.         return m;   
  30.     }   
  31.   
  32.     public void setM() throws MethodException, ClassNotFoundException,   
  33.             SecurityException, NoSuchMethodException {   
  34.         if (name == null || name.equals(""))   
  35.             throw new MethodException();   
  36.         if (c == null)   
  37.             throw new ClassNotFoundException();   
  38.         m = c.getDeclaredMethod(name, HttpServletRequest.class,   
  39.                 HttpServletResponse.class);   
  40.     }   
  41.   
  42.     public String getName() {   
  43.         return name;   
  44.     }   
  45.   
  46.     public void setName(String name) {   
  47.         this.name = name;   
  48.     }   
  49. }  
package com.pig.hub.dev.frameWork.action.config;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.pig.hub.dev.frameWork.action.exception.MethodException;

public class MethodBean implements java.io.Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -5753278542873561978L;
	private Class c;
	private Method m;
	private String name;
	

	public Class getC() {
		return c;
	}

	public void setC(Class c) {
		this.c = c;
	}

	public Method getM() {
		return m;
	}

	public void setM() throws MethodException, ClassNotFoundException,
			SecurityException, NoSuchMethodException {
		if (name == null || name.equals(""))
			throw new MethodException();
		if (c == null)
			throw new ClassNotFoundException();
		m = c.getDeclaredMethod(name, HttpServletRequest.class,
				HttpServletResponse.class);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

 通过 m = c.getDeclaredMethod(name, HttpServletRequest.class,  HttpServletResponse.class);得到url对应的方法对象。

下面就简单了

m.invoke(c.newInstance(), request, response);

执行而已。

 

现在通过契约式的url可以访问到相应的对象了。那么还差一个如何跳转。

首先我们自定义一个annotation

Java代码 复制代码
  1. package com.pig.hub.dev.frameWork.annotation;   
  2.   
  3. import java.lang.annotation.ElementType;   
  4. import java.lang.annotation.Retention;   
  5. import java.lang.annotation.RetentionPolicy;   
  6. import java.lang.annotation.Target;   
  7.   
  8. /**  
  9.  *   
  10.  */  
  11. @Retention(RetentionPolicy.RUNTIME)   
  12. @Target(ElementType.METHOD)   
  13. public @interface MappingConfig {   
  14.   
  15.     String success();   
  16.   
  17.     String fail();   
  18.   
  19.     String exception();   
  20.   
  21. }  
package com.pig.hub.dev.frameWork.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MappingConfig {

	String success();

	String fail();

	String exception();

}

 其中有三个属性,success fail exception分别指在成功后跳转的地方或者失败后跳转的。。。

下面是在实际对象中如何使用这三个对象。

Java代码 复制代码
  1. public class aa {   
  2.     @MappingConfig(success="../index.jsp",fail="",exception="")   
  3.     public void bb(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {   
  4.         System.out.print("test------------");   
  5.         request.setAttribute("123""成功了");   
  6.     }   
  7.   
  8. }  
public class aa {
	@MappingConfig(success="../index.jsp",fail="",exception="")
	public void bb(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.print("test------------");
		request.setAttribute("123", "成功了");
	}

}

 然后通过

Java代码 复制代码
  1. package com.pig.hub.dev.frameWork.action;   
  2.   
  3. import java.lang.reflect.Method;   
  4. import java.util.HashMap;   
  5.   
  6. import com.pig.hub.dev.frameWork.action.exception.MappingException;   
  7. import com.pig.hub.dev.frameWork.annotation.MappingConfig;   
  8.   
  9. public class MappingUtil {   
  10.     @SuppressWarnings("unchecked")   
  11.     public static HashMap makeHashMap(Method m) throws MappingException {   
  12.         MappingConfig an = m.getAnnotation(MappingConfig.class);   
  13.   
  14.         if (an == null)   
  15.             throw new MappingException();   
  16.         HashMap map = new HashMap();   
  17.   
  18.         map.put("success", an.success());   
  19.         map.put("fail", an.fail());   
  20.         map.put("exception", an.exception());   
  21.         return map;   
  22.   
  23.     }   
  24.   
  25. }  
package com.pig.hub.dev.frameWork.action;

import java.lang.reflect.Method;
import java.util.HashMap;

import com.pig.hub.dev.frameWork.action.exception.MappingException;
import com.pig.hub.dev.frameWork.annotation.MappingConfig;

public class MappingUtil {
	@SuppressWarnings("unchecked")
	public static HashMap makeHashMap(Method m) throws MappingException {
		MappingConfig an = m.getAnnotation(MappingConfig.class);

		if (an == null)
			throw new MappingException();
		HashMap map = new HashMap();

		map.put("success", an.success());
		map.put("fail", an.fail());
		map.put("exception", an.exception());
		return map;

	}

}

 

得到要执行的方法上的annotation然后将他属性放入一个hashmap中。

下面就是跳转了(成功的)


   request.getRequestDispatcher((String) map.get("success")).forward(
     request, response);

 

这样就完成了一个基于url契约的零配置mvc的实现。

呵呵,实在有点简单,问题也很多。

写这个东西的目的其实在于学习一下java的基本知识。现在大家没事干就说这样那样的框架,我想不如自己来试着如何实现。通过自己来实现,可以明白好多东西,然后在去用那写框架我想会更加得心应手。

以上纯属功能上的实现,问题很多很多,例如在actionservlet中有一大堆的异常,这样写出来很别扭,其中还有自己定义的异常。

欢迎大家给我提出建议。

你可能感兴趣的:(java,框架,mvc,servlet,C#)