Servlet是如何实现MVC的
Servlet是一种服务器端的编程语言,是J2EE中比较关键的组成部分,Servlet技术的推出,扩展了Java语言在服务器端开发的功能,巩固了Java语言在服务器端开发中的地位,而且现在使用非常广泛的JSP技术也是基于Servlet的原理.
JSP+JavaBeans+Servlet成为实现MVC模式的一种有效的选择。
如果我们要实现一个对用户的增删改查,并且要求符合对扩展开发,对修改关闭的原则,该怎么做呢?
首先,这是我们的类图以及类与类之间调用的时序图。
根据UML图来实现代码:
TestServlet类
- 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);
- }
- }
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
- 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;
- }
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; }
添加类,这里就只写添加类了,其他类一样
- 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”;
- }
- }
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配置
- <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>
<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,所以,这就不符合对扩展开发,对修改关闭原则,所以,我们需要把这部分提取出来,配置到配置文件里,用反射进行配置。
我们需要先配置配置文件
- <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>
<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对象
- 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”
- }
- }
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,达到我们的目的。
- 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);
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);
这样,我们基本就是实现了对扩展开发,对修改封闭的原则,但是,这仅仅是一个功能我们就需要做这么多事情,写这么多代码,对程序员来说这是一项不小的工作量,那么我们有没有其他的办法让我们的工作量小一点呢?