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);  
    }  
  
}  

抽象接口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 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>  

这里我们发现,在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>  

需要获取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"  
    }  
  }  

最后根据获取的对象采用反射来动态实例化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);  

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java初学

j2ee—框架(1):Servlet+JSP实现基本的登录功能(v1.0)

4678
来自专栏游戏杂谈

webgame开发中的文件加密

一般的webgame中都会对资源、消息进行加密,这里只是简单记录一下对文件的加密过程。

1833
来自专栏java沉淀

servlet+jsp/js二种实现方式:三级联动(附加demo代码)

2323
来自专栏Java Web

初学Java Web(9)——学生管理系统(简易版)总结

项目开始时间:2018年4月8日14:37:47 项目完成时间:2018年4月9日10:03:30 技术准备 这个项目是自己用于巩固 J2EE 相关知识的练...

6395
来自专栏Flutter入门

Weex是如何在Android客户端上跑起来的

Weex可以通过自己设计的DSL,书写.we文件或者.vue文件来开发界面,整个页面书写分成了3段,template、style、script,借鉴了成熟的MV...

4275
来自专栏闻道于事

JavaWeb(五)Filter过滤器

Filter过滤器 Fileter介绍 Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理...

4706
来自专栏xingoo, 一个梦想做发明家的程序员

文件上传之Apache commons fileupload使用

  文件上传的方法主要目前有两个常用的,一个是SmartUpload,一个是Apache的Commons fileupload.   我们这里主要介绍下第二个的...

2549
来自专栏算法修养

java后台设计简单的json数据接口,设置可跨域访问,前端ajax获取json数据

在开发的过程中,有时候我们需要设计一个数据接口。有时候呢,数据接口和Web服务器又不在一起,所以就有跨域访问的问题。 第一步:简单的设计一个数据接口。 数据接口...

5667
来自专栏Java成神之路

Java微信公众平台开发_07_JSSDK图片上传

(2)对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式 (即 key1=value1&key2=value2…)拼接成...

3601
来自专栏Hongten

spring+hibernate+JQuery开发_电子相册_源码

=============================================================

4404

扫码关注云+社区

领取腾讯云代金券