Servlet笔记(二)

来源:互联网 发布:中国城市癌症最新数据 编辑:程序博客网 时间:2024/06/09 22:49
    一、ServletContext(非常重要)
 
1、作用:每一个JavaWeb应用都会有唯一的ServletContext对象。
             在Tomcat加载应用时,就创建该对象的实例。(ServletContext是一个接口,它的实例类由服务器提供)
实现servlet之间数据共享
public   class   ServletContextDemo1Servlet   extends  HttpServlet {
     public   void  doGet(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
        ServletConfig config = getServletConfig();//只为当前 Servlet 服务
        ServletContext sc = config.getServletContext();
        sc.setAttribute( "p" ,  "ppp" );     }
public   class   ServletContextDemo2Servlet   extends  HttpServlet {
     public   void  doGet(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
         //只为当前 Servlet 服务
        ServletConfig config = getServletConfig();
         //只要是当前应用,不论是谁,得到的ServletContext都是同一个对象
        ServletContext sc = config.getServletContext();
        Object  obj  = sc.getAttribute( "p" );     }
2、得到ServletContext的实例:
        ServletConfig   getServletContext()
     public   void  doGet(HttpServletRequest req, HttpServletResponse resp)
             throws  ServletException, IOException {
         //获取当前服务的 config ,只为当前 Servlet 服务
        ServletConfig config = getServletConfig();
         //获取ServletContext对象,就可以对ServletContext进行操作了.
         //只要是当前应用,不论是谁,得到的ServletContext都是同一个对象
         //就是说ServletContext的范围比 Servlet 还要大
        ServletContext sc = config.getServletContext();
         // 此句是另一个 Servlet 上设置数据sc.setAttribute("q"," qqq ");
         //读取并打印数据
        resp.getOutputStream().write(((String)sc.getAttribute( "q" )).getBytes());
         //如果先运行Demo2,则会报错,空指针异常,必须先向ServletContext存值,才可以取出             }
3、读取应用级的参数
        web.xml中:
        <context-param><!-- 配置的是应用全局参数,读取应该使用ServletContext -->
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>   
      </context-param>
     public   void  doGet(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
         //实际开发需要删掉this.因为这是多余的.在这里写出来是为了明确HttpServlet里面有这个方法
        ServletContext sc =  this .getServletContext();
         //读取对象,打印到控制台上
        String str = sc.getInitParameter( "encoding" );
        System. out .println(str);     }
4、实现Servlet的转发。
public   class   ServletContextDemo4Servlet   extends  HttpServlet {
     //演示转发:ServletContext转发的。源,转发到Demo5,最后显示的是Demo5的信息
     public   void  doGet(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
        response.getOutputStream().write( "I am 4" .getBytes());
        ServletContext sc = getServletContext();
         //请求分发器  path,目标路径,该路径必须以"/"开头。斜线代表的是当前应用/day04_00_servletContext
        RequestDispatcher rd = sc.getRequestDispatcher("/servlet/ServletContextDemo5Servlet" );
         //必须forward一下,否则不会转发
        rd.forward(request, response);     }
5、读取配置文件(*.properties   *.xml)
 方式一:利用ServletContext
     特点:用于Web环境下。可以读取应用任何目录下的任何文件
     //利用ServletContext读取cfg3.properties
     private   void   test3(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException  {
        String realPath = getServletContext().getRealPath("/WEB-INF/classes/com/itheima/servlet/cfg3.properties" );
         //创建Properties类来读取文件内容。
        Properties props =  new  Properties();
         //用FileInputStream流来关联 。
        props.load( new   FileInputStream (realPath));
        String value = props.getProperty( "hello" );
        response.getOutputStream().write(value.getBytes());
    }
     //利用ServletContext读取cfg2.properties
     private   void   test2(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException  {
        String realPath = getServletContext().getRealPath("/WEB-INF/classes/cfg2.properties" );
        Properties props =  new  Properties();
        props.load( new  FileInputStream(realPath));
        String value = props.getProperty( "hello" );
        response.getOutputStream().write(value.getBytes());
    }
     //利用ServletContext读取cfg1.properties
     private   void   test1(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException  {
        String realPath = getServletContext().getRealPath("/WEB-INF/cfg1.properties" );
        Properties props =  new  Properties();
        props.load( new  FileInputStream(realPath));
        String value = props.getProperty( "hello" );
        response.getOutputStream().write(value.getBytes());     }
 
方式二:利用ResourceBundle
     特点:可以用在非web环境和Web环境下。专门读取properties文件的,只能读取类路径中的properties文件
     //利用ResourceBundle(国际化)读取cfg3.properties
     private   void   test5(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException  {
         //注意使用的是基名
        ResourceBundle rb = ResourceBundle. getBundle ("com.itheima.servlet.cfg3" );
        response.getOutputStream().write(rb.getString( "hello" ).getBytes());
    }    
     //利用ResourceBundle(国际化)读取cfg2.properties
     private   void   test4(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException  {
        ResourceBundle rb = ResourceBundle. getBundle ("cfg2" );//基名
        response.getOutputStream().write(rb.getString( "hello" ).getBytes());     }
 
方式三:利用类加载器(更加专业)
     特点:可以用在非web环境和Web环境下,可以读取类路径中的任何配置文件,不适合读取特别大的文件
     //利用类加载器读取cfg3.properties的真实路径
     private   void  test8(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
         //获得类加载器,用类加载器获得指定资源路径
        ClassLoader cl = ServletContextDemo7Servlet.class .getClassLoader();
        URL url = cl.getResource( "com/itheima/servlet/cfg3.properties" );
         //得到真实的绝对路径。如果该路径有空格或有中文,构建流时报错
        String realPath = url.getPath();
        InputStream in =  new  FileInputStream(realPath);
        Properties props =  new  Properties();
        props.load(in);
        String value = props.getProperty( "hello" );
        response.getOutputStream().write(value.getBytes());
    }    
    
     //利用类加载器读取cfg3.properties,注意资源路径
     private   void   test7(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException  {
         //获得类加载器,再用类加载器获得指定资源的输入流
        ClassLoader cl = ServletContextDemo7Servlet.class .getClassLoader();
        InputStream in = cl.getResourceAsStream("com/itheima/servlet/cfg3.properties" );
        Properties props =  new  Properties();
        props.load(in);
        String value = props.getProperty( "hello" );
        response.getOutputStream().write(value.getBytes());
    }
     //利用类加载器读取cfg2.properties,注意资源路径
     private   void   test6(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException  {
        ClassLoader cl = ServletContextDemo7Servlet.class .getClassLoader();
        InputStream in = cl.getResourceAsStream("cfg2.properties" );
        Properties props =  new  Properties();
        props.load(in);
        String value = props.getProperty( "hello" );
        response.getOutputStream().write(value.getBytes());     }
 
二、Servlet规范中的核心接口类图(非常重要)
 
    javax.servlet.Servlet
    javax.servlet.GenericServlet
    javax.servlet.http.HttpServlet
    javax.servlet.ServletContext
    javax.servlet.RequestDispatcher
    javax.servlet.ServletConfig
    javax.servlet.ServletRequest
    javax.servlet.ServletResponse
 
 
三、响应对象HttpServletResponse(非常重要)
    1、输出数据中文编码
     //利用字节流输出中文数据
     private   void  test3(HttpServletResponse response)  throws  IOException {
         int  data = 97;
        ServletOutputStream out = response.getOutputStream();
         //如果不加转成字符串,会输出a
        out.write((data+ "" ).getBytes());
    }
     private   void   test2(HttpServletResponse response)  throws  IOException  {
        String data =  "陈冠希爱阿娇" ;
        ServletOutputStream out = response.getOutputStream();
         //通知浏览器,服务端使用的编码
        response.setContentType( "text/html;charset=UTF-8" );//记住
         byte  b[] = data.getBytes( "UTF-8" );
        out.write(b);
    }
     //用本地平台默认编码输出:没有乱码
     private   void   test1(HttpServletResponse response)  throws  IOException  {
        String data =  "中国" ;
        ServletOutputStream out = response.getOutputStream();
         byte  b[] = data.getBytes();
        out.write(b);
    }
     //日后使用
     private   void   test1(HttpServletResponse response)  throws  IOException  {
        String data =  "李宗瑞李宗盛" ;
         //更改字符流默认查询的码表 只对post提交有效
        response.setCharacterEncoding( "UTF-8" );
         //通知浏览器解码用什么编码
        response.setContentType( "text/html;charset=UTF-8" );
        
        PrintWriter out = response.getWriter();
        out.write(data); //默认查ISO-8859-1 规范要求     }
 
   2、一些应用案例(响应头的应用)
   下载中文文件名的文件
     public   void  doGet(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
             //得到输入流:路径该怎么获取,斜线就代表当前应用
            String path =  "/WEB-INF/阿娇.jpg" ;
             //截取文件名,包含头,所以要+1,把/排出
            String filename = path.substring(path.lastIndexOf("/" )+1);
             //告知客户端以下载的方式打开
            response.setHeader( "Content-Disposition" ,  "attachment;filename="+URLEncoder. encode (filename,  "UTF-8" ));
            response.setHeader( "Content-Type" ,  "application/octet-stream" );
             //根据相对于当前应用的路径,得到绝对路径
            String realPath = getServletContext().getRealPath(path);
             //下面打印:C:\ apache - tomcat -6.0.35\ webapps \day04_01_response\WEB-INF\阿娇. jpg
            System. out .println(realPath);
            InputStream in =  new  FileInputStream(realPath);
            OutputStream out = response.getOutputStream();
             int  len = -1;
             byte  b[] =  new   byte [1024];
             while ((len=in.read(b))!=-1){
                out.write(b, 0, len);
            }
            in.close();
            out.close();     }
 
  输出CAPTCHA图像,就是验证图片
     public   void  doGet(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
         //通知浏览器,图片不要缓存
        response.setHeader( "Expires" ,  "-1" );
        response.setHeader( "Cache-Control" ,  "no-cache" );
        response.setHeader( "Pragma" ,  "no-cache" );
        
         int  width = 120;
         int  height = 25;
         //搞出代表内存图片的对象BufferedImage,然后取画笔:开始画
        BufferedImage image =  new  BufferedImage(width,height,BufferedImage. TYPE_INT_RGB );
        Graphics g = image.getGraphics();
         //填充背景
        g.setColor(Color. YELLOW );
        g.fillRect(0, 0, width, height);
         //画边框
        g.setColor(Color. BLUE );
        g.drawRect(1, 1, width-2, height-2);
         //画干扰线
        g.setColor(Color. GRAY );
        Random r =  new  Random();
         for ( int  i=0;i<30;i++)
            g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
         //写随机验证码
        g.setColor(Color. RED );
        g.setFont( new  Font("宋体" ,Font. BOLD|Font. ITALIC ,18));
         //数字
//        for( int  i=1;i<5;i++){
//            g.drawString(r.nextInt(10)+"", x*22, 20);
//            x+=20;
//        }
         // 汉字的,随意添加即可
        String base =  "\u7684\u4e00\u4e86\u662f\u6211\u4e0d\u5728" ;
         int  x = 22;
         for ( int  i=1;i<5;i++){
            g.drawString(base.charAt(r.nextInt(base.length()))+"" , x*22,20);
            x+=20;
        }
         //输出到页面上:ImageIO
        ImageIO. write (image,  "jpg" , response.getOutputStream());     }
 
    控制浏览器定时刷新
     //定时刷新到别处
     private   void  test2(HttpServletResponse response)  throws  IOException {
        response.setContentType( "text/html;charset=UTF-8" );
        response.setHeader( "Refresh" ,  "2;url=http://www.itheima.com" );
        response.getWriter().write( "注册成功!2秒后自动转向主页" );
    }
     //定时2秒就刷新自己
     private   void   test1(HttpServletResponse response)  throws  IOException  {
        response.setIntHeader( "Refresh" , 2);     }
 
控制缓存的有效期
     public   void  doGet(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
         //相对于当前时间的。如果值比当前时间的毫秒值小,倒退1小时。
        response.setDateHeader( "Expires" , System. currentTimeMillis ()+1*60*60*1000);     }
 
 3、一些细节
    a,字节流和字符流不能同时使用
    b,服务器会自动关闭流
    c,Servlet向ServletOutputStream或PrintWriter对象中写入的数据,将被Tomcat从response里面获取,Tomcat将这些数据当作响应消息的正文,
然后再与响应状态行和各响应头组合后输出到客户端。
四、请求对象HttpServletRequest(非常重要)
    1、常用方法
     public   void  doGet(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
         //打印客户端的 url 地址
        String url= request.getRequestURL().toString();
         //打印客户端的 uri 地址
         String  uri= request.getRequestURI();
         //打印客户端的GET返回值
        String queryString = request.getQueryString();
         //打印客户端的访问IP地址
        String remoteAddr = request.getRemoteAddr();
         //打印客户端的访问port
         int  remotePort = request.getRemotePort();
         //打印客户端的提交数据方式
        String method = request.getMethod();     }
 
    2、获取请求消息头
     public   void  doGet(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
        System. out .println( "----------------" );
         //获取所有的请求消息头和值
         Enumeration  e = request.getHeaderNames();
         //用while循环.这个类的方法不多,hasMoreElements判断里面是否还有
         while (e.hasMoreElements()){
            String headerName = (String)e.nextElement();
            System. out .println(headerName+ ":::::" +request.getHeader(headerName));
        }
    }
 
    3、获取请求参数    
     //获取所有的请求参数值
     private   void   test4(HttpServletRequest request, PrintWriter out)  {
         //key: String请求参数名字   value:String[]  请求参数值
        Map<String,String[]> map=  request.getParameterMap() ;
         for (Map.Entry<String, String[]> me:map.entrySet()){
            System. out .println(me.getKey()+ "=" +Arrays. asList (me.getValue()));
        }
    }
     //获取所有的请求参数值
     private   void   test3(HttpServletRequest request, PrintWriter out)  {
         Enumeration  e = request.getParameterNames();//所有的请求参数名
         while (e.hasMoreElements()){
            String  paramName  = (String)e.nextElement();
            System. out .println( paramName + "=" +Arrays. asList (request.getParameterValues( paramName )));
        }
    }
     //获取重名的请求参数值
     private   void   test2(HttpServletRequest request, PrintWriter out)  {
         //同样的key可能会有多个value,所以取回的value是数组
        String[]  passwords  = request.getParameterValues("password" );
    }
     //获取单一的请求参数值
     private   void   test1(HttpServletRequest request, PrintWriter out)  {
         //用户所有的界面输入都是String类型,如果表单的输入域没有name属性,浏览器根本不传递数据
        String  username  = request.getParameter("username" );//
        String  password  = request.getParameter("password" );     }
 
    4、常用表单及数据的获取
     //**封装数据到JavaBean中:遵循了一个约定,表单字段名和User中的属性(getter setter)一致
     private   void  test10(HttpServletRequest request, PrintWriter out) {
         try  {
            User user =  new  User();
            System. out .println( "封装前:" +user);
             //String-->基本类型:自动转换。
             //日期的不会:注册类型转换器
//            ConvertUtils.register(new Converter() {
//                public Object convert(Class type, Object value) {
//                    DateFormat  df  = new SimpleDateFormat(" yyyy -MM- dd ");
//                    if(type==Date.class){
//                        //要把String转成Date
//                        String s = (String)value;
//                        try {
//                            return df.parse(s);
//                        } catch (ParseException e) {
//                            throw new RuntimeException(e);
//                        }
//                    }else if(type==String.class){
//                        //把Date转成String
//                        Date date = (Date)value;
//                        return df.format(date);
//                    }
//                    return null;
//                }
//            }, Date.class);
            
            ConvertUtils. register ( new  DateLocaleConverter(), Date.class );//请看上面注释
            
            BeanUtils. populate (user, request.getParameterMap()); //原理看test7
            System. out .println( "封装后:" +user);
        }  catch  (Exception e) {
            e.printStackTrace();
        }
        
    }
     //**封装数据到JavaBean中:遵循了一个约定,表单字段名和User中的属性(getter setter)一致
     private   void   test8(HttpServletRequest request, PrintWriter out)  {
         try  {
            User user =  new  User();
            System. out .println( "封装前:" +user);
            BeanUtils. populate (user, request.getParameterMap()); //原理看test7
            System. out .println( "封装后:" +user);
        }  catch  (Exception e) {
            e.printStackTrace();
        }     }
 
(反射及内省)
     //封装数据到JavaBean中:遵循了一个约定,表单字段名和User中的属性(getter setter)一致
     private   void   test6(HttpServletRequest request, PrintWriter out)  {
         try  {
            Map<String, String[]> map=  request.getParameterMap() ;
            User user =  new  User();
            System. out .println( "封装前:" +user);
             //封装
             for (Map.Entry<String, String[]> me:map.entrySet()){
                String paramName = me.getKey();//请求参数名   和User中的属性(getter setter)一致
                String[] paramValue = me.getValue();//请求参数值                 
                 //属性描述其
                PropertyDescriptor pd =  new  PropertyDescriptor(paramName, User.class );
                 //调用其中的setter方法
                Method method = pd.getWriteMethod();
                 if (paramValue!= null&¶mValue. length>1){//看如何反射main方法
                    method.invoke(user, (Object)paramValue);
                } else {
                     method.invoke(user,paramValue) ;
                }
            }
            System. out .println( "封装后:" +user);
        }  catch  (Exception e) {
            e.printStackTrace();
        }              }
 
以流的形式获取请求正文内容
     private   void   test9(HttpServletRequest request, PrintWriter out)  throws  IOException  {
        ServletInputStream in = request.getInputStream();
         int  len = -1;
         byte  b[] =  new   byte [1024];
         while ((len=in.read(b))!=-1){
            System. out .println( new  String(b,0,len));
        }
        in.close();     }
    5、请求转发和重定向
    6、请求范围的域对象
0 0
原创粉丝点击