我一个朋友初学JAVA,让我给他讲讲Web开发这方面的东西,老实说几年前用过的Struts现在早就忘光了...
平常接些JAVA单子基本也就用 nutz 和 spring mvc ,sese [自己拼的一个小框架] 这3种东西
但是这些对初学者似乎还是很复杂.
让我给他讲 struts 确实不会,就按我的思路给讲好了 ... 以上都是废话...
作为现在流行的java web开发框架,基本都是MVC导向的... 此处我就歪歪下自己的想法
剥掉 M 就只剩余 C + V ,把 JSP+JSTL+EL 指向 模版视图[V] , 那么把V完全可以无视了,此时只剩下控制器 C
现在很多框架把 控制器 使用非Servlet的类来实现,方便测试吧,可能... 那么此处也就遵循好了,方便测试吧...
public abstract class BaseController { protected IRequestEntry requestEntry ; public void init(){} public abstract boolean executeAction(String actionName) ; public static BaseController newInstance(String controllerClass) { try { Object controller = Class.forName(controllerClass).newInstance(); if (controller instanceof BaseController){ return (BaseController) controller ; } } catch(ClassNotFoundException ex){} catch(Exception ex){} return null ; } public IRequestEntry getRequestEntry() { return requestEntry; } public void setRequestEntry(IRequestEntry requestEntry) { this.requestEntry = requestEntry; } }
这样的控制器应该能够接受吧,算是基础类了吧... 无论是 spring mvc 还是 struts 基本都有一个分发器对象,用来将请求发送到 指定的控制器/Action里面,此处衍生了N多的XML配置文件,这样的我很不喜欢,说白了就是单一入口 的功能呗
我很讨厌 XML配置文件,很无语... 当初使用XML的目的,我感觉 应该是为了 解耦合和自定义常用参数 ... 可惜到现在膨胀到
方方面面 写代码的同时还要写XML,还美其名曰 为了解耦和 我不知道到底实现了没有 反正我不喜欢... 这也是我为什么从JAVA转行到PHP的原因之一.... 可能是我畏惧吧
IRequestEntry
作用就是 请求的入口点 里面封装了 常用的一些 方法:
public interface IRequestEntry extends IDataService { public String getRequestParameter(String parameter) ; public void setView(String view,String format) ; public void setView(String view) ; public void assign(String key,Object value) ; public boolean isPost() ; public boolean isGet() ; public boolean isAjax() ; }
IDataService
interface IDataService { public void service(Object request) throws Exception ; }
请求的入口点 的作用 最明显的就是 充当 分发器...
为了尽可能的不使用 配置文件 这里使用 惯例设置吧 通过URI中挂载的参数 来传递 控制器 和 action 名字进来 , 并通过这些信息来加载指定的控制器对象,这里
HttpRequestEntry
public class HttpRequestEntry extends HttpServlet implements IRequestEntry { // 控制器基本信息 private String controllerPackage = "" , currentController = "Application" ,currentAction = "index" ; private String viewBaseDir = "" ; private HttpServletRequest request = null ; public void init() throws ServletException { super.init(); this.setControllerPackage(this.getInitParameter("controllerPackage")); this.setViewBaseDir(this.getInitParameter("viewBaseDir")) ; // ServletContext context = this.getServletContext(); // -- load and init db pool } public void service(Object request) throws ControllerNotFound,ActionNotFound { // parseURI -- load controller String controllerClass = this.getControllerClass(this.currentController) ; BaseController controller = BaseController.newInstance(controllerClass) ; if (controller != null){ controller.setRequestEntry(this); boolean isExistAction = controller.executeAction(this.currentAction); if (!isExistAction){ throw new ActionNotFound(controllerClass,this.currentAction) ; } }else { throw new ControllerNotFound(controllerClass) ; } } /** * 每次Http请求,此方法仅仅执行一次 */ public void service(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException { this.request = request ; this.setCurrentController(request.getParameter("controller")); this.setCurrentAction(request.getParameter("action")); try { this.service(request); } catch (ControllerNotFound ex) { System.out.println(ex.getLocalizedMessage()); } catch (ActionNotFound ex) { System.out.println(ex.getLocalizedMessage()); } String viewName = this.getView() ; if (viewName != null){ // 渲染视图 String viewPath = "" ; if (this.viewBaseDir.endsWith("/")) viewPath = this.viewBaseDir + viewName ; else viewPath = this.viewBaseDir + "/" + viewName ; RequestDispatcher rd = this.getServletContext().getRequestDispatcher(viewPath); if (rd != null){ rd.forward(request, response); }else { System.out.println("cannot load view file: " + viewPath); } } } // public boolean forward(String path){} // public boolean redirect(String uri,int timeout){} public String getRequestParameter(String parameter){ return this.request.getParameter(parameter) ; } public void setView(String view,String format){ this.request.setAttribute("#view#",view) ; } public String getView(){ Object view = request.getAttribute("#view#") ; return view != null ? (String) view : null ; } public void setView(String view){ this.request.setAttribute("#view#","JSP") ; } public void assign(String key,Object value){ this.request.setAttribute(key, value) ; } public boolean isPost(){ return this.request.getMethod().equals("POST"); } public boolean isGet(){ return this.request.getMethod().equals("GET"); } public boolean isAjax(){ String r = this.request.getHeader("HTTP_X_REQUESTED_WITH") ; if (r != null && "xmlhttprequest".equals(r.toLowerCase())) return true ; return false ; } public String getControllerClass(String controller){ return this.controllerPackage == "" ? controller : this.controllerPackage + "." + controller ; } public String getCurrentController() { return this.currentController; } public void setCurrentController(String currentController) { if (currentController == null || "".equals(currentController.trim())) currentController = "Application" ; else currentController = com.moogens.Toolkit.toUpperFirstChar(currentController) ; this.currentController = currentController ; } public String getCurrentAction() { return this.currentAction; } public void setCurrentAction(String currentAction) { this.currentAction = currentAction == null ? "index" : currentAction ; } public String getControllerPackage() { return controllerPackage; } public void setControllerPackage(String controllerPackage) { this.controllerPackage = controllerPackage == null ? "" : controllerPackage; } public String getViewBaseDir() { return viewBaseDir; } public void setViewBaseDir(String viewBaseDir) { if (viewBaseDir == null || "".equals(viewBaseDir.trim() )) viewBaseDir = "/WEB-INF/views" ; if (!viewBaseDir.startsWith("/")) viewBaseDir = "/" + viewBaseDir ; String realBaseDir = getServletContext().getRealPath(viewBaseDir); File baseDir=new File(realBaseDir); if(!baseDir.exists()) baseDir.mkdir(); this.viewBaseDir = viewBaseDir; } }
重要的代码,此处因为每次HTTP请求只会执行1次,所以在这个方法里面去处理请求 并 负责常规的一些操作即可
public void service(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException { this.request = request ; this.setCurrentController(request.getParameter("controller")); this.setCurrentAction(request.getParameter("action")); try { this.service(request); } catch (ControllerNotFound ex) { System.out.println(ex.getLocalizedMessage()); } catch (ActionNotFound ex) { System.out.println(ex.getLocalizedMessage()); } String viewName = this.getView() ; if (viewName != null){ // 渲染视图 String viewPath = "" ; if (this.viewBaseDir.endsWith("/")) viewPath = this.viewBaseDir + viewName ; else viewPath = this.viewBaseDir + "/" + viewName ; RequestDispatcher rd = this.getServletContext().getRequestDispatcher(viewPath); if (rd != null){ rd.forward(request, response); }else { System.out.println("cannot load view file: " + viewPath); } } }
真正的数据处理的地方,加载控制器,执行action
public void service(Object request) throws ControllerNotFound,ActionNotFound { // parseURI -- load controller String controllerClass = this.getControllerClass(this.currentController) ; BaseController controller = BaseController.newInstance(controllerClass) ; if (controller != null){ controller.setRequestEntry(this); boolean isExistAction = controller.executeAction(this.currentAction); if (!isExistAction){ throw new ActionNotFound(controllerClass,this.currentAction) ; } }else { throw new ControllerNotFound(controllerClass) ; } }
控制器的一个例子
public final class Application extends BaseController { public Application() { // TODO: Add your code here } // 这个方法由子类自己实现,至于里面有多少个action 已经 action 对应的方法名字等等 必须在这里面 public boolean executeAction(String action) { if (action.equals("index")){ this.indexAction(); return true ; }else if (action.equals("show")){ this.showAction(); return true ; } return false ; } protected void indexAction(){ this.requestEntry.assign("title",this.toString() + " [indexAction]"); this.requestEntry.setView("application.jsp","JSP"); } protected void showAction(){ this.requestEntry.assign("title",this.toString() + " [showAction]"); this.requestEntry.setView("application.jsp","JSP"); } }
基本Over了 这样的代码 在 Tomcat6上 确实可以跑 不知道效率怎么样 我也不知道 .... 应该是够简单明了的
我从接触计算机书籍的第一天起, 就认准一个死理:”如果你想从垃圾堆中找点吃的, 那么你就买中国人写的计算机书籍吧.”
------------------------------------------------------
做过小结: 附件代码