一直以来对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 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>
<?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代码
- 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;
- }
- ---------------------------------------------------------
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;
}
---------------------------------------------------------
- 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;
- }
- -------------------------------------------------------
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;
}
-------------------------------------------------------
- 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);
- }
- }
- }
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)来构建一个自定义的方法对象。
- 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;
- }
- }
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
- 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();
- }
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分别指在成功后跳转的地方或者失败后跳转的。。。
下面是在实际对象中如何使用这三个对象。
- 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", "成功了");
- }
- }
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", "成功了");
}
}
然后通过
- 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;
- }
- }
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中有一大堆的异常,这样写出来很别扭,其中还有自己定义的异常。
欢迎大家给我提出建议。