Servlet是如何实现MVC的 .



Servlet是如何实现MVC的  

Servlet是一种服务器端的编程语言,是J2EE中比较关键的组成部分,Servlet技术的推出,扩展了Java语言在服务器端开发的功能,巩固了Java语言在服务器端开发中的地位,而且现在使用非常广泛的JSP技术也是基于Servlet的原理.

JSP+JavaBeans+Servlet成为实现MVC模式的一种有效的选择。

 

如果我们要实现一个对用户的增删改查,并且要求符合对扩展开发,对修改关闭的原则,该怎么做呢?

首先,这是我们的类图以及类与类之间调用的时序图。

 

 

根据UML图来实现代码:

TestServlet类

  1. package com.bjpowernode.servlet;
  2. import java.io.IOException;
  3. import java.util.List;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. public class TestServlet extends HttpServlet {
  9.     protected void doGet(HttpServletRequest request, HttpServletResponse response)
  10.             throws ServletException, IOException {
  11.         String requestURI = request.getRequestURI();
  12.         System.out.println(“requestURI=” + requestURI);
  13.         String path = requestURI.substring(requestURI.indexOf(“/”,1),requestURI.indexOf(“.”));
  14.         System.out.println(“path = ” +path);
  15.         String username = request.getParameter(“username”);
  16.         Action action = null;
  17.         if(“/servlet/delUser”.equals(path)){
  18.             action = new DelUserAction();
  19.         }else if(“/servlet/addUser”.equals(path)){
  20.             action = new AddUserAction();
  21.         }else if(“/servlet/modifyUser”.equals(path)){
  22.             action = new ModifyAction();
  23.         }else if(“/servlet/queryUser”.equals(path)){
  24.             action = new QueryUserAction();
  25.         }else{
  26.             throw new RuntimeException(“请求失败”);
  27.         }
  28.         String forward =”";
  29.         try {
  30.             forward= action.execute(request, response);
  31.         } catch (Exception e) {
  32.             e.printStackTrace();
  33.         }
  34.         request.getRequestDispatcher(forward).forward(request, response);
  35.     }
  36.     protected void doPost(HttpServletRequest request, HttpServletResponse response)
  37.             throws ServletException, IOException {
  38.         doGet(request,response);
  39.     }
  40. }
package com.bjpowernode.servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String requestURI = request.getRequestURI();
		System.out.println("requestURI=" + requestURI);
		String path = requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
		System.out.println("path = " +path);

		String username = request.getParameter("username");

		Action action = null;
		if("/servlet/delUser".equals(path)){
			action = new DelUserAction();
		}else if("/servlet/addUser".equals(path)){
			action = new AddUserAction();
		}else if("/servlet/modifyUser".equals(path)){
			action = new ModifyAction();
		}else if("/servlet/queryUser".equals(path)){
			action = new QueryUserAction();
		}else{
			throw new RuntimeException("请求失败");
		}
		String forward ="";
		try {
			forward= action.execute(request, response);
		} catch (Exception e) {
			e.printStackTrace();
		}
		request.getRequestDispatcher(forward).forward(request, response);

	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request,response);
	}

}

抽象接口Action

 

  1. package com.bjpowernode.servlet;
  2. import javax.servlet.http.HttpServletRequest;
  3. import javax.servlet.http.HttpServletResponse;
  4. public interface Action {
  5.     public String execute(HttpServletRequest request, HttpServletResponse response)
  6.     throws Exception;
  7. }
package com.bjpowernode.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public interface Action {

	public String execute(HttpServletRequest request, HttpServletResponse response)
	throws Exception;

}

 


添加类,这里就只写添加类了,其他类一样

  1. package com.bjpowernode.servlet;
  2. import javax.servlet.http.HttpServletRequest;
  3. import javax.servlet.http.HttpServletResponse;
  4. public class AddUserAction implements Action {
  5.     public String execute(HttpServletRequest request,
  6.             HttpServletResponse response) throws Exception {
  7.         String username = request.getParameter(“username”);
  8.         //int age = Integer.parseInt(request.getParameter(“username”));
  9.         //String sex = request.getParameter(“sex”);
  10.         //调用业务逻辑
  11.         UserManager userManager = new UserManager();
  12.         userManager.add(username);
  13.         return ”/add_success.jsp”;
  14.     }
  15. }
package com.bjpowernode.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AddUserAction implements Action {

	public String execute(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String username = request.getParameter("username");
		//int age = Integer.parseInt(request.getParameter("username"));
		//String sex = request.getParameter("sex");

		//调用业务逻辑
		UserManager userManager = new UserManager();
		userManager.add(username);

		return "/add_success.jsp";
	}

}

Web.xml配置

  1. <welcome-file-list>
  2.     <welcome-file>index.jsp</welcome-file>
  3.   </welcome-file-list>
  4.   <servlet>
  5.     <servlet-name>TestServlet</servlet-name>
  6.     <servlet-class>com.bjpowernode.servlet.TestServlet</servlet-class>
  7.   </servlet>
  8.   <servlet-mapping>
  9.      <servlet-name>TestServlet</servlet-name>
  10.      <!–
  11.      <url-pattern>/servlet/TestServlet</url-pattern>
  12.       –>
  13.       <url-pattern>*.do</url-pattern>
  14.   </servlet-mapping>
<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <servlet>
  	<servlet-name>TestServlet</servlet-name>
  	<servlet-class>com.bjpowernode.servlet.TestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
     <servlet-name>TestServlet</servlet-name>
     <!-- 
     <url-pattern>/servlet/TestServlet</url-pattern>
      -->
      <url-pattern>*.do</url-pattern>
  </servlet-mapping>

 

这里我们发现,在testAction类中,用到了大量的if和else,而当我们需要扩展一个上传类的时候,就需要修改if/else,所以,这就不符合对扩展开发,对修改关闭原则,所以,我们需要把这部分提取出来,配置到配置文件里,用反射进行配置。

 

我们需要先配置配置文件

  1. <action-config>
  2.         <action path =”/servlet/delUser” type = ”com.bjpowernode.servlet.DelUserAction”>
  3.             <forward name = ”success”>del_success.jsp</forward>
  4.             <forward name = ”error”>del_error.jsp</forward>
  5.         </action>
  6.         <action path =”/servlet/addUser” type = ”com.bjpowernode.servlet.AddUserAction”>
  7.             <forward name = ”success”>add_success.jsp</forward>
  8.             <forward name = ”error”>add_error.jsp</forward>
  9.         </action>
  10.         <action path =”/servlet/modifyUser” type = ”com.bjpowernode.servlet.ModifyAction”>
  11.             <forward name = ”success”>modify_success.jsp</forward>
  12.             <forward name = ”error”>modify_error.jsp</forward>
  13.         </action>
  14.         <action path =”/servlet/queryUser” type = ”com.bjpowernode.servlet.QueryUserAction”>
  15.             <forward name = ”success”>query_success.jsp</forward>
  16.             <forward name = ”error”>query_error.jsp</forward>
  17.         </action>
  18.   </action-config>
		<action-config>
		 		<action path ="/servlet/delUser" type = "com.bjpowernode.servlet.DelUserAction">
		  			<forward name = "success">del_success.jsp</forward>
		  			<forward name = "error">del_error.jsp</forward>
		  		</action>	
		  		<action path ="/servlet/addUser" type = "com.bjpowernode.servlet.AddUserAction">
		  			<forward name = "success">add_success.jsp</forward>
		  			<forward name = "error">add_error.jsp</forward>
		  		</action>	
		  		<action path ="/servlet/modifyUser" type = "com.bjpowernode.servlet.ModifyAction">
		  			<forward name = "success">modify_success.jsp</forward>
		  			<forward name = "error">modify_error.jsp</forward>
		  		</action>	
		  		<action path ="/servlet/queryUser" type = "com.bjpowernode.servlet.QueryUserAction">
		  			<forward name = "success">query_success.jsp</forward>
		  			<forward name = "error">query_error.jsp</forward>
		  		</action>	
		  </action-config>

需要获取actionMapping对象

  1. ActionMapping{
  2.     private String path;
  3.     private String type;
  4.    Map forwardMap;
  5.   }
  6.   forwardMap{
  7.     key = ”success”;
  8.     value =”/del_success.jsp”
  9.     key =”error”
  10.     value =”del_error.jsp”;
  11.   }
  12.   Map map = new HashMap();
  13.   map.put(“/servlet/delUser”,actionMapping);
  14.   map.put(“/servlet/addUser”,actionMapping);
  15.   map.put(“/servlet/modifyUser”,actionMapping);
  16.   map.put(“/servlet/queryUser”,actionMapping);
  17.  // 如果是删除ActionMapping存储如下:
  18.   actionMapping{
  19.     path =”/servlet/delUser”;
  20.    type =”com.bjpowernode.servlet.DelUserAction”
  21.     forwardMap{
  22.         key =”success”,value =”/del_success.jsp”
  23.         key =”error”,value”/del_error.jsp”
  24.     }
  25.   }
  ActionMapping{
		  	private String path;
			private String type;
		   Map forwardMap;

		  }
		  forwardMap{
		  	key = "success";
		  	value ="/del_success.jsp"
		  	key ="error"
		  	value ="del_error.jsp";

		  }

		  Map map = new HashMap();
		  map.put("/servlet/delUser",actionMapping);
		  map.put("/servlet/addUser",actionMapping);
		  map.put("/servlet/modifyUser",actionMapping);
		  map.put("/servlet/queryUser",actionMapping);

		 // 如果是删除ActionMapping存储如下:
		  actionMapping{
		  	path ="/servlet/delUser";
		   type ="com.bjpowernode.servlet.DelUserAction"
		   	forwardMap{
		   		key ="success",value ="/del_success.jsp"
		   		key ="error",value"/del_error.jsp"
		   	}
		  }

最后根据获取的对象采用反射来动态实例化Action,达到我们的目的。

  1.  String path = ”/servlet/delUser”;
  2. /  根据截取的URL请求,到Map中取得本次请求对应的Action
  3.     ActionMapping actionMapping =(ActionMapping)map.get(path);
  4. /取得本次请求对应的Action类的完整路径
  5.  String type = actionMapping.getType();  //com.bjpowernode.servlet.DelUserAction
  6. // 采用反射动态实例化Action
  7.  Action action  = (Action)class.forName(type).newInstance();
  8. /动态待用Action中的execute方法
  9.  String forward = action.execute(request.response);
  10.  //根据路径完成转向
  11. request.getRequestDispatcher(forward).forward(request, response);
		  String path = "/servlet/delUser";

		//  根据截取的URL请求,到Map中取得本次请求对应的Action
		  	ActionMapping actionMapping =(ActionMapping)map.get(path);

		//取得本次请求对应的Action类的完整路径
		  String type = actionMapping.getType();  //com.bjpowernode.servlet.DelUserAction

		 // 采用反射动态实例化Action
		  Action action  = (Action)class.forName(type).newInstance();

		//动态待用Action中的execute方法
		  String forward = action.execute(request.response);

		  //根据路径完成转向		 
		 request.getRequestDispatcher(forward).forward(request, response);

 

        这样,我们基本就是实现了对扩展开发,对修改封闭的原则,但是,这仅仅是一个功能我们就需要做这么多事情,写这么多代码,对程序员来说这是一项不小的工作量,那么我们有没有其他的办法让我们的工作量小一点呢?