zoukankan      html  css  js  c++  java
  • 《JavaWeb从入门到改行》关于BaseServlet那些事

    @为什么需要BaseServlet?  我们知道一个POST或者GET提交对应着一个Servlet, 无数的提交会让Servlet页面增加,我们希望一个Servlet就能处理很多提交的请求。

    @BaseServlet 是一个继承了HttpServlet的普通类,并不是Servlet类,所以不需要在web.xml中添加路径。但是Servlet会继承这个BaseServlet来实现一个Servlet处理多个提交请求 。

    @一些要求 是: 客户端发送请求时,必须提供一个参数(本文编写的这个参数名字叫method,这个method和form中的那个method没有半毛钱关系,只是一个变量名字而已),用来说明要调用Servlet中的那个处理方法; 其次,继承了BaseServlet的Servlet中的处理请求的方法的原型必须与service方法相同,即返回值类型、参数都不需要和service方法相同。即如下的形式:

     public String XXX(HttpServletRequest request, HttpServletResponse 
                     response) throws ServletException, IOException {
        
            return null ;
        }

    @POST和GET请求对于method参数的提供技巧 POST请求一般为表单形式,提供method参数的方式可以添加一个隐藏字段 <input type="hidden" name="method" value="希望调用Servlet中的方法的名字"/>  ; @GET请求一般为超链接,提供method参数的方式直接在路径后面加 ?method=方法名 

    @POST和GET请求编码处理 我们知道Servlet对POST请求和对GET请求的请求编码不同,区别如下:

    POST的请求
    request.setCharacterEncoding("utf-8");
    String name =  request.getParameter("name");
    GET的请求
    String name =  request.getParameter("name");
    name = new String(name.getBytes("ISO-8859-1"),"utf-8");
    POST和GET的响应编码都是:
    response.setContentType("text/html;charset=UTF-8");

    为了使得servlet中的代码简洁,我们可以把两种编码的代码放到BaseServlet中,但是,像上传下载这种请求不适合用BaseServlet,所以我们一般把这种代码写在过滤器中,过滤器不是本文主要内容,如果你不会的话,可以不用过滤器,把编码的代码直接写在servlet中的请求处理方法中即可 。 

    @源码

    1 <%--get请求,传递过去method参数,指明调用TestServlet的fun2方法,并且传递一个参数param--%>
    2 <a href="<c:url value='/TestServlet?method=fun2&param=哈哈'/>"> 点击这里啊</a>
    3 <%--post请求--%>
    4 <form action="<c:url value='/TestServlet'/>" method="post">
    5    <input type="hidden" name="method" value="fun1"/>
    6    <input type="text" name="param" value="我是表单参数" />
    7    <input type="submit" name="提交"/>
    8 </form>
    请求jsp页面
     1 package cn.demo1.baseServlet;
     2 
     3 import java.io.IOException;
     4 
     5 import javax.servlet.ServletException;
     6 import javax.servlet.http.HttpServletRequest;
     7 import javax.servlet.http.HttpServletResponse;
     8 /**
     9  * TestServlet 
    10  *    实现了一个Servlet中多个请求处理方法
    11  *    方法的的参数必须和service方法相同
    12  *    客户端必须传递过来method参数,说明是调用哪一个请求处理方法
    13  * @author ZHAOYUQIANG
    14  *
    15  */
    16 public class TestServlet extends BaseServlet {
    17     /**
    18      * 测试post传递过来的参数
    19      * @param request
    20      * @param response
    21      * @return
    22      * @throws ServletException
    23      * @throws IOException
    24      */
    25     public String fun1(HttpServletRequest request, HttpServletResponse response)
    26             throws ServletException, IOException {
    27         String param = request.getParameter("param");
    28         request.setAttribute("param", param);
    29         return "f:/baseServlet/index.jsp" ;
    30     }
    31     /**
    32      * 测试get请求传递过来的参数
    33      * @param req
    34      * @param resp
    35      * @return
    36      * @throws ServletException
    37      * @throws IOException
    38      */
    39     public String fun2(HttpServletRequest request, HttpServletResponse response)
    40             throws ServletException, IOException {
    41         String param = request.getParameter("param");
    42         request.setAttribute("param", param);
    43         return "f:/baseServlet/index.jsp";
    44     }
    45 }
    请求Servlet
      1 package cn.demo1.baseServlet;
      2 
      3 import java.io.IOException;
      4 import java.lang.reflect.Method;
      5 
      6 import javax.servlet.ServletException;
      7 import javax.servlet.http.HttpServlet;
      8 import javax.servlet.http.HttpServletRequest;
      9 import javax.servlet.http.HttpServletResponse;
     10 /**
     11  * BaseServlet[抽象类] 不需要在web.xml中添加路径
     12  * @功能 1. 
     13  * @author ZHAOYUQIANG
     14  *
     15  */
     16 public abstract class BaseServlet extends HttpServlet {
     17     public void service(HttpServletRequest request, HttpServletResponse response)
     18             throws ServletException, IOException {
     19 //        response.setContentType("text/html;charset=UTF-8");//处理响应编码
     20         /*
     21          * 设置POST和GET请求编码
     22          */                
     23         /*
     24          * 1. 获取参数,用来识别用户想请求的方法
     25          *      method是用户在浏览器地址栏中输入的想要调用的方法,是个参数
     26          */
     27         String methodName = request.getParameter("method");
     28         /*
     29          * 2. 判断用户有没有传参数
     30          */
     31         if(methodName == null || methodName.trim().isEmpty()){
     32             throw new RuntimeException("您没有传递method参数! 无法确定您要调用的方法!");
     33         }
     34         /**
     35          * 3. 判断是哪一个方法,是哪一个就调用哪一个
     36          *    所用的技术是: 反射
     37          *        需要得到本类Class,然后调用它的getMethod,通过传递过来的方法名字进行得到Method对象
     38          *    这样做的目的是: 以后像其他Servlet中的方法要修改或者添加新方法时,就不用在去修改这一块代码了
     39          */
     40         /*
     41          * 3.1.  得到当前类的对象
     42          */
     43         Class c = this.getClass();
     44         /*
     45          * 3.2.  通过传递过来的方法名(addUse等)得到Method对象
     46          *    导包 :java.lang.reflect.Method;
     47          */
     48         Method method = null ;
     49         try {
     50             method = c.getMethod(methodName, 
     51                     HttpServletRequest.class,HttpServletResponse.class);
     52         } catch (Exception e) {
     53             throw new RuntimeException("您要调用的方法"+methodName+",它不存在");
     54         } 
     55         try {
     56             /*
     57              * 3.3. 调用method表示的方法,即: 调用继承该类的类中的方法
     58              *     反射调用: 用this来调用method表示的方法,并且传递参数req和resp
     59              */
     60             String result =(String)method.invoke(this, request,response);
     61             /**
     62              * 4. 处理从继承这个类的类中返回的字符串(重定向和转发)
     63              *     return "r:/index.jsp"; 和 return "f:/index.jsp";
     64              *      返回的是字符串,需要解读字符串
     65              */
     66             /*
     67              * 4.1. 如果用户返回的字符串为null,或者"",那么什么都不做
     68              */
     69             if(result == null || result.trim().isEmpty()){
     70                 return  ;
     71             }
     72             /*
     73              * 4.2. 解读字符串1:判断字符串中有没有冒号
     74              *        没有冒号默认表示转发,反之再进行判断
     75              */
     76             if(result.contains(":")){
     77                 /*
     78                  * 4.3. 解读字符串2 : 先获取冒号位置,然后截取前缀(操作,是重定向还是转发)和后缀(路径)
     79                  */
     80                 int index = result.indexOf(":");
     81                 String operate = result.substring(0,index);
     82                 String path = result.substring(index+1);
     83                 /*
     84                  * 4.4. 进行处理,如果是r重定向,如果是f则转发
     85                  */
     86                 if(operate.equalsIgnoreCase("r")){
     87                     response.sendRedirect(request.getContextPath()+path);
     88                 }else if(operate.equalsIgnoreCase("f")){
     89                     request.getRequestDispatcher(path).forward(request, response);
     90                 }else{
     91                     throw new RuntimeException("您指定的操作"+operate+
     92                             "不支持,请正确填写:r和f");
     93                 }                                
     94             }else{
     95                 /*
     96                  * 没有冒号默认转发处理
     97                  */
     98                 request.getRequestDispatcher(result).forward(request, response);
     99             }                                            
    100         } catch (Exception e) {
    101             System.out.println("您要调用的方法"+methodName+",它内部抛出了异常");
    102             throw new RuntimeException(e);
    103         }            
    104     }
    105 }
    BaseServlet
     1 package cn.demo1.baseServlet;
     2 
     3 import java.io.IOException;
     4 import javax.servlet.Filter;
     5 import javax.servlet.FilterChain;
     6 import javax.servlet.FilterConfig;
     7 import javax.servlet.ServletException;
     8 import javax.servlet.ServletRequest;
     9 import javax.servlet.ServletResponse;
    10 import javax.servlet.http.HttpServletRequest;
    11 
    12 /**
    13  * 辅助Servlet简化编码代码
    14  */
    15 public class EncodingFilter implements Filter {
    16 
    17     public void destroy() {
    18         // TODO Auto-generated method stub
    19     }
    20     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    21         /*
    22          * 处理post请求乱码问题
    23          */
    24         request.setCharacterEncoding("utf-8");
    25         /*
    26          * 处理GET请求编码问题
    27          *   String name1 =  request.getParameter("name");
    28          *   name2 = new String(name.getBytes("ISO-8859-1"),"utf-8");
    29          *    GET不一样,设置编码后,servlet中获取name,获取应该是name2,都是如果如上写的话,
    30          *     getParameter("name")获取的是name1 .
    31          * 掉包request
    32          *    1. 写一个request的装饰类
    33          *    2. 放行时,使用我们自己的request
    34          *    3. 但是POST方式依然使用request
    35          */
    36         HttpServletRequest req = (HttpServletRequest) request ;
    37         if(req.getMethod().equals("GET")){
    38             EncodingRequest er = new EncodingRequest(req);     
    39             chain.doFilter(er, response);
    40         }else if(req.getMethod().equals("POST")){
    41             chain.doFilter(request, response);
    42         }
    43         response.setContentType("text/html;charset=UTF-8");
    44     }
    45 
    46     public void init(FilterConfig fConfig) throws ServletException {
    47         // TODO Auto-generated method stub
    48     }
    49 
    50 }
    EncodingFilter类
    package cn.demo1.baseServlet;
    
    import java.io.UnsupportedEncodingException;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    /**
     * 辅助过滤器来处理GET编码问题
     * @author ZHAOYUQIANG
     *
     */
    public class EncodingRequest extends HttpServletRequestWrapper{
    private HttpServletRequest request ;
        
        public EncodingRequest(HttpServletRequest request) {
            super(request);
            this.request = request ;
        }
        /**
         * 处理编码问题
         */
        public String getParameter(String name) {
            String value = request.getParameter(name);
            /*
             * 处理编码问题
             */
            try {
                value = new String (value.getBytes("ISO-8859-1"),"utf-8");
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                throw new RuntimeException(e);
            }
            
            return value;
        }
    
    }
    EncodingRequest类
    1 <filter>
    2     <display-name>EncodingFilter</display-name>
    3     <filter-name>EncodingFilter</filter-name>
    4     <filter-class>cn.demo1.baseServlet.EncodingFilter</filter-class>
    5   </filter>
    6   <filter-mapping>
    7     <filter-name>EncodingFilter</filter-name>
    8     <url-pattern>/TestServlet</url-pattern>
    9   </filter-mapping>
    过滤器的拦截配置

    @项目下载

    http://files.cnblogs.com/files/zyuqiang/webBlogTest.rar

  • 相关阅读:
    Linux GCC常用命令
    用两个栈实现一个队列(转载)
    BMP格式介绍(一)
    图像处理笔记(1): bmp文件结构处理与显示
    大数据竞赛平台——Kaggle 入门篇
    图像识别中的深度学习
    面向对象中的抽象和具体类的理解
    全排列算法
    少有程序员读的书
    照片回执
  • 原文地址:https://www.cnblogs.com/zyuqiang/p/7406290.html
Copyright © 2011-2022 走看看