这个框架也是为google app engine准备的。当时感觉直接在gae上sevlet太烦人了,就封装个简易的框架。使用的时候只需要配置web.xml中DispacherSevlet和package.properties中的package.path(默认扫描的包)即可
gae例子: http://orzblogs.appspot.com/Home.htm (记得自己找梯子。。。)
首先声明:gae本身就是个玩具。这个web框架也是为了玩玩具而做的玩具。。。性能很有问题,不过gae上也无所谓了。不用多久conetxt就全被清空了。所以全当玩具玩吧,理念可以可以看下。
gae例子: http://orzblogs.appspot.com/Home.htm (记得自己找梯子。。。)
首先声明:gae本身就是个玩具。这个web框架也是为了玩玩具而做的玩具。。。性能很有问题,不过gae上也无所谓了。不用多久conetxt就全被清空了。所以全当玩具玩吧,理念可以可以看下。
大学的时候很BS java,学了之后就扔掉了,现在工作了才开始接触java。
java在web方面如果不是开源,不是众多的java框架支持,那么它确实没什么值得称道的。
倒是jvm被优化的不错。
java web框架本质上都是sevlet,所有的那么web框架都是对sevlet进行了封装,然后对web相关的进行包装。那么我们也可以来diy个简易的web框架,为的是体验这个中间的过程,可能框架不实用,甚至不能称作框架,其实为的就是减少一点配置,虽然现在springMVC通过注解就可以减少web层的配置,这里所做的也是同样的事,性能肯定很差,但是也是一种方法,增加理解而已。
首先任何web框架的入口基本上都是一个XXdispatcher。用来进行请求url的转发。
OK,那么我们就来做一个面向web请求的简易的不能称为框架的框架。前端使用velicity进行渲染。
当然一定要把spring给集成进来,要不谁给我们持久化bean呢。
首先通过DispacherSevlet来进行请求的转发。然后根据请求的名称加载bean。然后通过反射将bean的相关属性注入。然后执行bean。然后获取需要渲染的模板。渲染。返回结果给用户。
java在web方面如果不是开源,不是众多的java框架支持,那么它确实没什么值得称道的。
倒是jvm被优化的不错。
java web框架本质上都是sevlet,所有的那么web框架都是对sevlet进行了封装,然后对web相关的进行包装。那么我们也可以来diy个简易的web框架,为的是体验这个中间的过程,可能框架不实用,甚至不能称作框架,其实为的就是减少一点配置,虽然现在springMVC通过注解就可以减少web层的配置,这里所做的也是同样的事,性能肯定很差,但是也是一种方法,增加理解而已。
首先任何web框架的入口基本上都是一个XXdispatcher。用来进行请求url的转发。
OK,那么我们就来做一个面向web请求的简易的不能称为框架的框架。前端使用velicity进行渲染。
当然一定要把spring给集成进来,要不谁给我们持久化bean呢。
首先通过DispacherSevlet来进行请求的转发。然后根据请求的名称加载bean。然后通过反射将bean的相关属性注入。然后执行bean。然后获取需要渲染的模板。渲染。返回结果给用户。
- public String doGet(HttpRequest request, HttpResponse response, Map<String, Object> context)
- public String doPost(HttpRequest request, HttpResponse response, Map<String, Object> context)
public String doGet(HttpRequest request, HttpResponse response, Map<String, Object> context)
public String doPost(HttpRequest request, HttpResponse response, Map<String, Object> context)
用户请求/Home.htm然后获取到对应的controller为Home。然后从框架IOC中获取Home。如果获取不到就通过bean加载器来加载Home,然后通过Home的dopost或者doget方法来处理应用。dopost和doget中会放入映射进去一个map<string,object>来存页面的上下文。当处理完毕后根据Home返回的页面路径来进行页面渲染,并将结果返回给用户。
细节:
1.维护一个自己的上下文用来存储所有的controller。当请求来的时候。先看上下文中是否存在这个controller,如果存在就不用去创建了,如果不存在创建之并且缓存到上下文中。
2.维护一个spring的上下文,当创建bean的时候从spring中获取相应的bean反射到要创建的bean相应的属性中。
3.前端用velicity进行渲染。实现control和主页面信息的隔离渲染。
使用步骤:
1.将jar包导入
2.配置web.xml中
- <servlet>
- <servlet-name>dispatcher</servlet-name>
- <servlet-class>org.jeasy.core.DispacherServlet</servlet-class>
- </servlet>
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.jeasy.core.DispacherServlet</servlet-class> </servlet>
3.在package.properties中的package.path包下增加类(如果访问Home.htm就增加Home.java
4.Home.java实现Controller接口,然后return 一个String类型,String为vm模板
核心代码:
DispacherSevlet
- public class DispacherServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
- private XmlWebApplicationContext applicationContext;
- private BeanLoaderService beanLoaderService;
- private PathResolver pathResolver;
- private ViewResolver viewResolver;
- private FrameWorkFlowManager frameWorkFlowManager;
- /**
- * 初始化应用信息
- *
- * @param config
- * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
- */
- public void init(ServletConfig servletConfig) throws ServletException {
- //初始化spring IOC
- applicationContext = new XmlWebApplicationContext();
- applicationContext.setServletConfig(servletConfig);
- applicationContext.refresh();
- //初始化jeasy IOC
- JEasyApplicationContext jEasyApplicationContext = new JEasyApplicationContext();
- //初始化bean加载器
- beanLoaderService = new BeanLoaderService(servletConfig.getServletContext(),applicationContext, jEasyApplicationContext);
- //初始化请求解析器
- pathResolver = new PathResolver();
- //初始化渲染器
- viewResolver=new VelocityResolver(servletConfig.getServletContext());
- //初始化工作流处理器
- frameWorkFlowManager=new FrameWorkFlowManager();
- super.init(servletConfig);
- }
- /**
- * 通过service来处理请求,不用以前的doPost和doGet
- * @param request
- * @param response
- * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
- */
- public void service(HttpServletRequest request, HttpServletResponse response){
- HttpRequest httpRequest = new HttpRequest(request);
- HttpResponse httpResponse = new HttpResponse(response);
- //初始化工作流处理器
- frameWorkFlowManager.init(beanLoaderService, viewResolver, httpRequest, httpResponse);
- //获取请求的地址信息
- String requestPath = request.getServletPath();
- String path=pathResolver.getPath(requestPath);
- //装备、执行、渲染
- frameWorkFlowManager.work(path);
- }
- }
public class DispacherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private XmlWebApplicationContext applicationContext;
private BeanLoaderService beanLoaderService;
private PathResolver pathResolver;
private ViewResolver viewResolver;
private FrameWorkFlowManager frameWorkFlowManager;
/**
* 初始化应用信息
*
* @param config
* @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
*/
public void init(ServletConfig servletConfig) throws ServletException {
//初始化spring IOC
applicationContext = new XmlWebApplicationContext();
applicationContext.setServletConfig(servletConfig);
applicationContext.refresh();
//初始化jeasy IOC
JEasyApplicationContext jEasyApplicationContext = new JEasyApplicationContext();
//初始化bean加载器
beanLoaderService = new BeanLoaderService(servletConfig.getServletContext(),applicationContext, jEasyApplicationContext);
//初始化请求解析器
pathResolver = new PathResolver();
//初始化渲染器
viewResolver=new VelocityResolver(servletConfig.getServletContext());
//初始化工作流处理器
frameWorkFlowManager=new FrameWorkFlowManager();
super.init(servletConfig);
}
/**
* 通过service来处理请求,不用以前的doPost和doGet
* @param request
* @param response
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public void service(HttpServletRequest request, HttpServletResponse response){
HttpRequest httpRequest = new HttpRequest(request);
HttpResponse httpResponse = new HttpResponse(response);
//初始化工作流处理器
frameWorkFlowManager.init(beanLoaderService, viewResolver, httpRequest, httpResponse);
//获取请求的地址信息
String requestPath = request.getServletPath();
String path=pathResolver.getPath(requestPath);
//装备、执行、渲染
frameWorkFlowManager.work(path);
}
}
首先在第一次创建的时候会初始化springIOC容器、自己的IOC容器、web层bean加载器、地址转换器、页面渲染、工作流
首先获请求的地址,然后进入工作流
BeanLoadService
- /**
- * bean的装配器
- *
- * @author yuezhen
- * @version $Id: ControllerLoadService.java,v 0.1 2009-9-24 上午09:35:09 yuezhen Exp $
- */
- public class BeanLoaderService {
- private static final Logger logger = Logger.getLogger(BeanLoaderService.class.getName());
- private ApplicationContext applicationContext;
- private JEasyApplicationContext jEasyContext;
- private String packagePath;
- /**
- * 获取spring的ioc容器和jeasy的ioc容器
- * @param applicationContext spring的ioc容器
- */
- public BeanLoaderService(ServletContext servletContext,ApplicationContext applicationContext,
- JEasyApplicationContext jEasyContext) {
- this.applicationContext = applicationContext;
- this.jEasyContext = jEasyContext;
- String rootPath = servletContext.getRealPath("/");
- logger.info("[jeasy] rootPath="+rootPath);
- Properties properties = new Properties();
- try {
- properties.load(new FileInputStream(rootPath
- + "/WEB-INF/package.properties"));
- } catch (Exception e) {
- logger.warning("[jeasy] can't load package.properties,rootPath="+rootPath);
- }
- packagePath = properties.getProperty("package.path","");
- if(!packagePath.equals("")){
- packagePath=packagePath+".";
- }
- }
- /**
- * 获取Controller
- * 如果在jeasy IOC中存在,直接读取
- * 如果在jeasy IOC中不存在,创建Controller,并放入jeasy IOC
- */
- public Controller getController(String name) {
- if (StringUtils.isBlank(name)) {
- return null;
- }
- Controller jEasyController = null;
- jEasyController = jEasyContext.getController(packagePath+name);
- //在jeasy IOC中不存在,创建Controller并存入IOC
- if (jEasyController == null) {
- logger.info("init bean:"+packagePath+name);
- jEasyController = this.createController(packagePath+name);
- jEasyContext.addController(packagePath+name, jEasyController);
- }
- return jEasyController;
- }
- /**
- * 通过反射创建controller
- * @param name
- * @return
- */
- public Controller createController(String name) {
- Controller controller = null;
- try {
- //获取controller
- controller = (Controller) Class.forName(name).newInstance();
- //包装controller,将set方法注入
- buildController(controller);
- } catch (ClassNotFoundException e) {
- logger.warning("[jeasy] can't find class named " + name);
- } catch (InstantiationException e) {
- } catch (IllegalAccessException e) {
- }
- return controller;
- }
- /**
- * 将controller里面所有的set方法全部注入
- * @param controller
- */
- public void buildController(Controller controller) {
- Class jEasyClass = controller.getClass();
- Field[] fields = jEasyClass.getDeclaredFields();
- for (Field field : fields) {
- String fieldName = field.getName();
- String method = "set" + fieldName.substring(0, 1).toUpperCase()
- + fieldName.substring(1);
- try {
- Method setMethod = jEasyClass.getMethod(method, new Class<?>[] { field.getType() });
- // 从springIOC中取得bean
- Object bean = applicationContext.getBean(field.getName());
- if(bean!=null){
- setMethod.invoke(controller, bean);
- }
- } catch (SecurityException e) {
- } catch (NoSuchMethodException e) {
- } catch (IllegalArgumentException e) {
- } catch (IllegalAccessException e) {
- } catch (InvocationTargetException e) {
- }
- }
- }
- }
/**
* bean的装配器
*
* @author yuezhen
* @version $Id: ControllerLoadService.java,v 0.1 2009-9-24 上午09:35:09 yuezhen Exp $
*/
public class BeanLoaderService {
private static final Logger logger = Logger.getLogger(BeanLoaderService.class.getName());
private ApplicationContext applicationContext;
private JEasyApplicationContext jEasyContext;
private String packagePath;
/**
* 获取spring的ioc容器和jeasy的ioc容器
* @param applicationContext spring的ioc容器
*/
public BeanLoaderService(ServletContext servletContext,ApplicationContext applicationContext,
JEasyApplicationContext jEasyContext) {
this.applicationContext = applicationContext;
this.jEasyContext = jEasyContext;
String rootPath = servletContext.getRealPath("/");
logger.info("[jeasy] rootPath="+rootPath);
Properties properties = new Properties();
try {
properties.load(new FileInputStream(rootPath
+ "/WEB-INF/package.properties"));
} catch (Exception e) {
logger.warning("[jeasy] can't load package.properties,rootPath="+rootPath);
}
packagePath = properties.getProperty("package.path","");
if(!packagePath.equals("")){
packagePath=packagePath+".";
}
}
/**
* 获取Controller
* 如果在jeasy IOC中存在,直接读取
* 如果在jeasy IOC中不存在,创建Controller,并放入jeasy IOC
*/
public Controller getController(String name) {
if (StringUtils.isBlank(name)) {
return null;
}
Controller jEasyController = null;
jEasyController = jEasyContext.getController(packagePath+name);
//在jeasy IOC中不存在,创建Controller并存入IOC
if (jEasyController == null) {
logger.info("init bean:"+packagePath+name);
jEasyController = this.createController(packagePath+name);
jEasyContext.addController(packagePath+name, jEasyController);
}
return jEasyController;
}
/**
* 通过反射创建controller
* @param name
* @return
*/
public Controller createController(String name) {
Controller controller = null;
try {
//获取controller
controller = (Controller) Class.forName(name).newInstance();
//包装controller,将set方法注入
buildController(controller);
} catch (ClassNotFoundException e) {
logger.warning("[jeasy] can't find class named " + name);
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
}
return controller;
}
/**
* 将controller里面所有的set方法全部注入
* @param controller
*/
public void buildController(Controller controller) {
Class jEasyClass = controller.getClass();
Field[] fields = jEasyClass.getDeclaredFields();
for (Field field : fields) {
String fieldName = field.getName();
String method = "set" + fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
try {
Method setMethod = jEasyClass.getMethod(method, new Class<?>[] { field.getType() });
// 从springIOC中取得bean
Object bean = applicationContext.getBean(field.getName());
if(bean!=null){
setMethod.invoke(controller, bean);
}
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
}
}
}
在bean加载器中会根据请求的url来加载bean。比如:请求/Home.htm,那么地址转化器会获取到bean的name为Home。然后会去加载Home的bean来当作Home的controller。将所有需要set的方法从SpringIOC中读出进行set,然后将Home以string,object的形式进行缓存。
FrameWorkFlowManager
- public class FrameWorkFlowManager {
- private static final Logger logger = Logger
- .getLogger(FrameWorkFlowManager.class.getName());
- private BeanLoaderService beanLoaderService;
- private ViewResolver viewResolver;
- private HttpRequest request;
- private HttpResponse response;
- public void init(BeanLoaderService beanLoaderService,
- ViewResolver viewResolver, HttpRequest request,
- HttpResponse response) {
- this.beanLoaderService = beanLoaderService;
- this.viewResolver = viewResolver;
- this.request = request;
- this.response = response;
- setResonse();
- }
- public void work(String path) {
- // 每次进行页面渲染,每个页面一个上下文
- Map<String, Object> context = new HashMap<String, Object>();
- Control control=new Control(viewResolver, response,context, request,beanLoaderService);
- context.put("control", control);
- render(path,context);
- }
- public void render(String path,Map<String, Object> context) {
- Controller controller = null;
- try {
- // 获取控制器对象
- controller = beanLoaderService.getController(path);
- } catch (Exception e) {
- }
- if (controller != null) {
- String result = null;
- try {
- // 调用Controller处理
- if (controller != null) {
- if (request.getMethod().equals("POST")) {
- result = controller.doPost(request, response, context);
- } else {
- result = controller.doGet(request, response, context);
- }
- } else {
- response.sendError(404);
- return;
- }
- } catch (Exception e) {
- }
- logger.info(result);
- try {
- if (result != null) {
- if (result.startsWith("redirect:")) {
- response.sendRedirect(result.substring("redirect:"
- .length()));
- } else {
- viewResolver.merge(result, context, response);
- }
- }
- } catch (Exception e) {
- }
- }
- }
- private void setResonse(){
- response.setCharacterEncoding(viewResolver.getCharacterEncoding());
- }
- }
public class FrameWorkFlowManager {
private static final Logger logger = Logger
.getLogger(FrameWorkFlowManager.class.getName());
private BeanLoaderService beanLoaderService;
private ViewResolver viewResolver;
private HttpRequest request;
private HttpResponse response;
public void init(BeanLoaderService beanLoaderService,
ViewResolver viewResolver, HttpRequest request,
HttpResponse response) {
this.beanLoaderService = beanLoaderService;
this.viewResolver = viewResolver;
this.request = request;
this.response = response;
setResonse();
}
public void work(String path) {
// 每次进行页面渲染,每个页面一个上下文
Map<String, Object> context = new HashMap<String, Object>();
Control control=new Control(viewResolver, response,context, request,beanLoaderService);
context.put("control", control);
render(path,context);
}
public void render(String path,Map<String, Object> context) {
Controller controller = null;
try {
// 获取控制器对象
controller = beanLoaderService.getController(path);
} catch (Exception e) {
}
if (controller != null) {
String result = null;
try {
// 调用Controller处理
if (controller != null) {
if (request.getMethod().equals("POST")) {
result = controller.doPost(request, response, context);
} else {
result = controller.doGet(request, response, context);
}
} else {
response.sendError(404);
return;
}
} catch (Exception e) {
}
logger.info(result);
try {
if (result != null) {
if (result.startsWith("redirect:")) {
response.sendRedirect(result.substring("redirect:"
.length()));
} else {
viewResolver.merge(result, context, response);
}
}
} catch (Exception e) {
}
}
}
private void setResonse(){
response.setCharacterEncoding(viewResolver.getCharacterEncoding());
}
}
对应的Spring、log4j的jar都要导入一块使用