我一个朋友初学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上 确实可以跑 不知道效率怎么样 我也不知道 .... 应该是够简单明了的
我从接触计算机书籍的第一天起, 就认准一个死理:”如果你想从垃圾堆中找点吃的, 那么你就买中国人写的计算机书籍吧.”
------------------------------------------------------
做过小结: 附件代码