zoukankan      html  css  js  c++  java
  • 【黑马旅游网】Servlet优化

    我们刚刚完成登录模块,每一个功能都对应了一个Servlet,非常的复杂。为了减少Servlet的数量,将其优化为一个模块一个Servlet,相当于在数据库中一张表对应一个Servlet,在Servlet中提供不同的方法,完成用户的请求。

    这个方法的核心就在于HttpServlet.service()方法。如下:

     /**
         * Receives standard HTTP requests from the public
         * <code>service</code> method and dispatches
         * them to the <code>do</code><i>XXX</i> methods defined in 
         * this class. This method is an HTTP-specific version of the 
         * {@link javax.servlet.Servlet#service} method. There's no
         * need to override this method.
         *
         * @param req   the {@link HttpServletRequest} object that
         *                  contains the request the client made of
         *                  the servlet
         *
         * @param resp  the {@link HttpServletResponse} object that
         *                  contains the response the servlet returns
         *                  to the client                                
         *
         * @exception IOException   if an input or output error occurs
         *                              while the servlet is handling the
         *                              HTTP request
         *
         * @exception ServletException  if the HTTP request
         *                                  cannot be handled
         * 
         * @see javax.servlet.Servlet#service
         */
        protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException
        {
            String method = req.getMethod();
    
            if (method.equals(METHOD_GET)) {
                long lastModified = getLastModified(req);
                if (lastModified == -1) {
                    // servlet doesn't support if-modified-since, no reason
                    // to go through further expensive logic
                    doGet(req, resp);
                } else {
                    long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                    if (ifModifiedSince < lastModified) {
                        // If the servlet mod time is later, call doGet()
                        // Round down to the nearest second for a proper compare
                        // A ifModifiedSince of -1 will always be less
                        maybeSetLastModified(resp, lastModified);
                        doGet(req, resp);
                    } else {
                        resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                    }
                }
    
            } else if (method.equals(METHOD_HEAD)) {
                long lastModified = getLastModified(req);
                maybeSetLastModified(resp, lastModified);
                doHead(req, resp);
    
            } else if (method.equals(METHOD_POST)) {
                doPost(req, resp);
                
            } else if (method.equals(METHOD_PUT)) {
                doPut(req, resp);
                
            } else if (method.equals(METHOD_DELETE)) {
                doDelete(req, resp);
                
            } else if (method.equals(METHOD_OPTIONS)) {
                doOptions(req,resp);
                
            } else if (method.equals(METHOD_TRACE)) {
                doTrace(req,resp);
                
            } else {
                //
                // Note that this means NO servlet supports whatever
                // method was requested, anywhere on this server.
                //
    
                String errMsg = lStrings.getString("http.method_not_implemented");
                Object[] errArgs = new Object[1];
                errArgs[0] = method;
                errMsg = MessageFormat.format(errMsg, errArgs);
                
                resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
            }
        }
    

    可以看出,这个方法会根据请求类型的不同,进行不同的调用。而我们的Servlet中只是用get和post请求,get请求也是调用post的函数,所以使用它来进行提取,再合适不过。所以我们需要做的就是建立一个公共提取Servlet,来进行不同请求方法的分发。

    以下是BaseServlet的代码:

    //@WebServlet(name = "BaseServlet")
    //不需要被访问到
    public class BaseServlet extends HttpServlet {
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("BaseServlet的service方法被执行了");
            //完成方法分发
            //1. 获取请求路径
            String uri = req.getRequestURI();
            System.out.println(uri);
            //2. 获取请求方法名称
            String methodName = uri.substring(uri.lastIndexOf("/") + 1);
            System.out.println(methodName);
            //3. 获取方法对象Method
            //谁调用我,我代表谁
            System.out.println(this);//UserServlet的对象
            try {
    //            //getDeclaredMethod()忽略访问权限修饰符,来获取方法
    //            Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
    //            //4. 执行方法
    //            //暴力反思
    //            method.setAccessible(true);
                Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
                method.invoke(this, req, resp);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
    
        }
    }
    
    1. 通过getRequestURI()来获取请求路径;
    2. 取最后的方法名;
    3. 通过getMethod()获取方法;
      其中getDeclaredMethod()忽略访问权限修饰符,来获取方法,这种方法可以获取包括私有方法之内的所有方法,这是不合适的,毕竟人家私有的东西,就不要访问了。所以我们使用getMethod(),并将请求方法的修饰符改成public。
    4. 通过invoke()执行。

    这样我们就可以通过UserServlet来继承BaseServlet,来实现一个模块对应一个Servlet。代码如下:

    @WebServlet("/user/*") // /user/add /user/find
    public class UserServlet extends BaseServlet {
        public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("UserServlet的add方法");
        }
    
        public void find(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("UserServlet的find方法");
        }
    }
    

    到这里,我们就可以把之前的方法全部集成到UserServlet了。

    不过别忘了优化还有两重要步骤:

    1. 抽取UserService
    2. 修改前端页面的请求

    看到这里,有了解SpringMVC或者SpringBoot的朋友应该明白了,Controller就是对BaseServlet的再次封装。不懂得朋友也不要紧,先混个眼熟,后面自然就明白了。

  • 相关阅读:
    ElasticSearch 之 Client
    Ubuntu 更新源
    ThinkPad 禁用 触摸板
    编译OpenGL代码时发生 Inconsistency detected by ld.so: dl-version.c: 224: _dl_check_map_versions: Assertion `needed != ((void *)0)' failed! 错误的解决方案
    python 自动认证登录
    RIDE的使用
    robotframework的分支和循环
    webdriver入门
    python字符串中的中文处理
    带认证的页面的自动认证登录
  • 原文地址:https://www.cnblogs.com/zllk/p/14367758.html
Copyright © 2011-2022 走看看