gae例子:http://orzblogs.appspot.com/Home.htm (記得自己找梯子。。。)
首先聲明:gae本身就是個玩具。這個web框架也是爲了玩玩具而做的玩具。。。性能很有問題,不過gae上也無所謂了。不用多久conetxt就全被清空了。所以全當玩具玩吧,理念可以可以看下。
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都要導入一塊使用