• Java Servlet开发的轻量级MVC框架最佳实践


    在Servlet开发的工程实践中,为了减少过多的业务Servlet编写,会采用构建公共Servlet的方式,通过反射来搭建轻量级的MVC框架,从而加快应用开发。

    关于Servlet开发的基础知识,请看:JavaWeb开发之详解Servlet及Servlet容器

    前后端交互的基本形式

    一般来说,前端提交数据请求有三种基本方式,分别是表单、链接和Ajax

    1. 按钮

    1 <form action="/BaseServlet/ServletDemo02?method=addStu" method="post">
    2     用户<input type="text" name="username"/><br/>
    3     <button>提交</button>
    4 </form>

    2. 链接

    <a href="/BaseServlet/ServletDemo02?method=delStu">删除学生</a><br/>

    3. Ajax

    1 <button onclick="fn()">按钮</button>
    2 <script>
    3 function fn(){
    4     $.post("/BaseServlet/ServletDemo02",{"method":"checkStu","user":"tom"},function(data){
    5         alert(data);
    6     });
    7 }

    在Servlet开发的语境中,它们的共同点都是:指定处理的Servlet类路径(在web.xml中指定)以及附带在请求中的“method”参数

    通过调用request参数匹配业务处理逻辑

    前端按照以上方法发起请求,Servlet容器就会把请求交给对应的Servlet处理,并且附带上形如 method=delStu 的参数,利用这个原理,就可以构建一个基础Servlet类,用来优化开发:

     1 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     2         //获取客户端提交到服务端的method对应的值
     3                 String md=request.getParameter("method");
     4                 //定义变量,存放功能执行完毕之后要转发的路径
     5                 String path=null;
     6                 
     7                 //通过判断md中不同的内容来决定本次功能
     8                 if("addStu".equals(md)){
     9                     path=addStu(request, response);
    10                 }else if("delStu".equals(md)){
    11                     path=delStu(request, response);
    12                 }else if("checkStu".equals(md)){
    13                     path=checkStu(request, response);
    14                 }else if("".equals(md)){
    15                     
    16                 }
    17                 if(null!=path){
    18                     //服务端的请求转发
    19                     request.getRequestDispatcher(path).forward(request, response);
    20                 }
    21     }
    22 
    23     
    24     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    25         doGet(request, response);
    26     }
    27     
    28     protected String addStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    29         System.out.println("添加学生");
    30         return "/test.html";
    31         
    32     }
    33     protected String delStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    34         System.out.println("删除学生");
    35         return "/test.html";
    36         
    37     }
    38     protected String checkStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    39         System.out.println("检查学生");
    40         response.getWriter().println("DDDDDD");
    41         return null;
    42     }

    以上的Servlet对请求进行了处理,通过获取index.html的请求,最后请求转发至目标页面,其核心思想是:

    1. 提取request的method参数的值;

    2. 定义变量,存储请求转发的路径;

    3. 通过判断method参数中的值的内容,来决定调用哪个业务功能。

    4. 完成业务功能后,使用请求转发处理

    通过反射匹配业务处理逻辑

    当业务量多的时候,以上实践仍是不够,此时比较好的方式就是采用反射。

     1 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     2         doGet(request, response);
     3     }
     4     
     5     public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     6         //获取客户端提交到服务端的method对应的值
     7         String md=request.getParameter("method");
     8         //定义变量,存放功能执行完毕之后要转发的路径
     9         String path=null;
    10         //获取到当前字节码对象(ServletDemo02.class在内存中对象)
    11         Class<? extends ServletDemo02> clazz = this.getClass();
    12         try {
    13             //获取clazz上名称为md, 参数为HttpServletRequest和HttpServletResponse的方法
    14             Method method=clazz.getMethod(md, HttpServletRequest.class,HttpServletResponse.class);
    15             if(null!=method){
    16                 //调用找到的方法
    17                 path=(String)method.invoke(this, request,response);
    18             }
    19             if(null!=path){
    20                 //服务端的转发
    21                 request.getRequestDispatcher(path).forward(request, response);
    22             }
    23         } catch (Exception e) {
    24             e.printStackTrace();
    25         }     
    26         
    27     }
    28 
    29     public String addStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    30         System.out.println("添加学生");
    31         return "/test.html";
    32         
    33     }
    34     public String delStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    35         System.out.println("删除学生");
    36         return "/test.html";
    37         
    38     }
    39     public String checkStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    40         System.out.println("检查学生");
    41         response.getWriter().println("DDDDDD");
    42         return null;
    43     }

    1. 提取request的method参数的值;

    2. 定义变量,存储请求转发的路径;

    3. 获取到当前Servlet对象在内存中的Class对象

    4. 获取Class对象上名称为md, 参数为HttpServletRequest和HttpServletResponse的方法

    5. 根据是否返回方法对象,调用业务功能并使用请求转发处理

    Java HttpServlet的父类GenericServlet,就是通过这个方法来调取HttpServlet的doGet或doPost方法的。

    最佳实践

    在实践开发中,一般会搭建一个BaseServlet,继承了HttpServlet并重写其Service方法,通过反射来找到业务功能子类对应的业务方法。

     1 public class BaseServlet extends HttpServlet {
     2     private static final long serialVersionUID = 12197442526341123L;
     3        
     4     @Override
     5     protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     6         System.out.println("service.....");
     7         //获取客户端提交到服务端的method对应的值
     8         String md=request.getParameter("method");
     9         //定义变量,存放功能执行完毕之后要转发的路径
    10         String path=null;
    11         //获取到当前字节码对象(ServletDemo02.class在内存中对象)
    12         Class<? extends BaseServlet> clazz = this.getClass();
    13         try {
    14             //获取clazz上名称为md方法
    15             Method method=clazz.getMethod(md, HttpServletRequest.class,HttpServletResponse.class);
    16             if(null!=method){
    17                 //调用找到的方法
    18                 path=(String)method.invoke(this, request,response);
    19             }
    20             if(null!=path){
    21                 //服务端的转发
    22                 request.getRequestDispatcher(path).forward(request, response);
    23             }
    24         } catch (Exception e) {
    25             e.printStackTrace();
    26         }
    27     }
    28 
    29 }

    而业务功能子类,则继承BaseServlet,专注于业务逻辑的开发

     1 public class ServletDemo03 extends BaseServlet {
     2 
     3     private static final long serialVersionUID = 11248215356242123L;
     4     
     5     public ServletDemo03() {
     6         System.out.println("没有参数的构造函数");
     7     }
     8     
     9     public String addStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    10         System.out.println("添加学生");
    11         return "/test.html";
    12         
    13     }
    14     public String delStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    15         System.out.println("删除学生");
    16         return "/test.html";
    17         
    18     }
    19     public String checkStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    20         System.out.println("检查学生");
    21         response.getWriter().println("DDDDDD");
    22         return null;
    23     }
    24 
    25 }
  • 相关阅读:
    sql注入-原理&防御
    vulnhub靶场之AI-WEB1.0渗透记录
    python -m http.server 搭建一个简易web下载服务器
    渗透测试工具-sqlmap
    OSI七层模型
    LAXCUS大数据操作系统3.03版本发布,欢迎使用试用
    松耦合和紧耦合的架构设计、性能对比
    Laxcus大数据操作系统2.0(5)- 第二章 数据组织
    从AlphaGo谈通用型人工智能设计
    基于深度推理、自编程、大数据的通用人工智能
  • 原文地址:https://www.cnblogs.com/leoliu168/p/9987193.html
Copyright © 2020-2023  润新知