Web之Servlet技术

1、web开发技术

  • 静态web资源的开发技术
    • Html
  • 常用动态web资源开发技术
    • JSP/Servlet、ASP、PHP等
    • 在java中,动态web资源开发技术统称为javaweb

2、常见的web服务器

  • weblogic:支持J2EE规范
  • websphere:支持J2EE规范
  • apache(tomcat):支持全部JSP以及Servlet规范,开源的
  • 常见的服务器端口地址:
    • http端口:80
    • smtp端口:25
    • pop3端口:110
    • ftp端口:23
    • https端口:443

3、web.xml文件

  • web应用的重要配置文件,一切涉及到对web应用中的web资源进行配置,都是在web.xml文件中进行设置的,如:

    • 1、某个web资源配置为网站首页(设置index.xml为首页)

      • <?xml version="1.0" encoding="ISO-8859-1"?>
        <web-app xmlns="http://java.sun.com/xml/ns/javaee"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
                version="3.0"
                metadata-complete="true">
            <welcome-file-list>
                <welcome-file>index.html</welcome-file>
            </welcome-file-list>
        </web-app>

    • 2、将Servlet程序映射到某个url地址上
    • 3、为web应用配置监听器
    • 4、为web应用配置过滤器
    • .....

4、虚拟主机的配置

  • 配置虚拟主机就是在tomcat服务器中配置一个网站
  • 如需要在web服务器中配置一个网站,需使用Host元素进行配置,如:

<Host name="site1" appBase="d:\app">
    <Context path="浏览器访问目录" docBase="应用的真实目录" />
<Host>
  • 配置的主机(网站)要想被外部访问,必须在DNS服务器或Windows系统中注册
  • 在Windows中的注册方式为修改计算机的hosts文件,如:

c:\Windows\System32\drivers\etc\hosts
在文件中添加如:
192.168.25.21(电脑IP)  www.djh.com
  • 对于web应用可以使用命令进行打包,后缀名打包为war,如:

  • web应用:news
    打包:jar -cvf news.war news
    
    • 对于打包后的war包,当拷贝到服务器目录(如:tomcat的webapps)下时会自动解压
    对于打包后的war包,当拷贝到服务器目录(如:tomcat的webapps)下时会自动解压

5、tomcat配置https连接器

  • 工具:

    keytool -genkey -alias tomcat -keyalg RSA
    -alias:表示的是定义别名为tomcat
    RSA:表示采用的算法
    
  • 配置:在tomcat服务器的server.xml文件中添加如下代码

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
           maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
           clientAuth="false" sslProtocol="TLS" 
           keystoreFile="上面工具产生的密钥库文件"
           keypass="上面工具中填入的密码"
    />  

6、HTTP协议

  • HTTP协议用于定义客户端与WEB服务器通讯的格式
  • 使用telnet程序连接web服务器,可以使用HTTP协议获取某个页面,快速了解HTTP协议的作用,如:

    扫描二维码关注公众号,回复: 161552 查看本文章
    在tomcat的webapps目录下有一个news应用,其中有一个1.html,则通过命令行输入下列命令可以连接并查看
        telnet localhost 8080(服务器端口)
        (回车)
        GET /news/1.html HTTP/1.1
        (连续回车两次可查看结果)
    
  • HTTP协议与平台无关
  • HTTP请求

    • 一个完整的HTTP请求包括以下内容:

      一个请求行、若干消息头、以及实体内容,如:
      请求行:(用于描述客户端的请求方式、请求的资源名称以及使用的HTTP协议版本)
          GET /news/my.html HTTP/1.1
      多个消息:(用于描述客户端请求的主机地址以及客户端的一些环境信息等)
          Accept: */*
          Accept-Language: en-us
          Connection: Keep-Alive
          Host: localhost
          Reference: http://localhost/link.asp
      
    • 请求方式有:

      POST、GET、HEAD、OPTIONS、DELETE、TRACE、PUT
      常用的为:GET与POST
      
      • 用户如没有设置,默认情况下浏览器向服务器发送的都是get请求
      • GET与POST的区别:

        • GET请求,可以在请求的URL地址后以?的形式带上提交给服务器的数据,多个数据之间以&进行分割,如:

          GET /mail/1.html?name=abc&password=123 HTTP/1.1
          
          • GET方式的特点:在URL地址后附带的参数是有限制的,其数据容量通常不能超过1K
        • POST请求,可以在请求的实体内容中向服务器发送数据
          • POST方式的特点:传送的数据量无限制
    • HTTP请求的常用头:

       Accept:text/html,image/*   (告诉服务器,客户端支持的数据格式)
       Accept-Charset:ISO-8859-1  (告诉服务器,客户端采用的编码)
       Accept-Encoding:gzip,compress  (告诉服务器,客户端支持的数据压缩格式)
       Accept-Language:en-us,zh-cn  (客户端的语言环境)
       Host:www.djh.com.cn:80      (表示请求的主机)
       if-Modified-Since:Tue, 11 Jul 2016 18:23:59 GMT    (告诉服务器,资源的缓存时间)
       Referer:http://www.djh.com.cn/index.jsp   (告诉服务器,是从哪个资源来访问服务器)
       User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36)   (客户机的软件环境)
       Cookie  (向服务器带数据)
       Connection:close(Keep-Alive)       (表示连接状态)
       Date:Thu, 11 Aug 2016 10:32:14 GMT 
      
  • HTTP响应

    • 一个HTTP响应代表服务器向客户端回送的数据,它包括:

      一个状态行、若干消息头以及实体内容
      
      • 如:

        HTTP/1.1 200 OK         //状态行(用于描述服务器对请求的处理结果)
        Server:Apache-Coyote/1.1        //多个响应头(用于描述服务器的基本信息以及数据的描述,服务器通过这些数据的描述信息,可以通知客户端如何处理等一会它送回来的数据)
        Date:Thu, 11 Aug 2016 10:32:14 GMT
        Content-Length: 18
        Content-Type:text/html
        Content-control:private
                                    //空行
        <HTML>                  //实体内容(代表服务器向客户端回送的数据)
        ....
        
    • 状态行:

      • 格式:

        HTTP版本号 状态码 原因叙述<CRLF>
        如:
            HTTP/1.1 200 OK
        

        -状态码用于表示服务器对请求的处理结果,它是一个三位的十进制数,响应状态码分为5类,如下:

        100~199:表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程
        200~299:表示成功接收请求并已完成整个处理过程,常用200
        300~399:为完成请求,客户需进一步细化请求,如:请求的资源已经移动一个新地址,常用302(会携带一个location)、304与307(和缓存相关)
        400~499:客户端的请求有错误,常用404、403
        500~599:服务器端出现错误,常用500
        
    • HTTP常用的响应头:

      Location:http://www.djh.com/index.jsp  (配合状态码302使用,用于告诉客户端寻找的资源)
      Server:Apache-Coyote/1.1    (告诉客户端服务器的类型)
      Content-Encoding:gzip   (告诉客户端数据使用的压缩格式)
      Content-Length:18
      Content-Language:zh-cn
      Content-Type:text/html; charset=GB2312  (通知客户端回送数据的类型)
      Last-Modified:Wed, 10 Aug 2016 11:32:19 GMT
      Refresh:1;url=http://www.djh.com   (通知客户端间隔多长时间刷新一次)
      Content-Disposition:attachment; filename=aaa.zip  (通知客户端以下载的方式打开数据,filename表示保存的文件名)
      Transfer-Encoding: chunked
      Set-Cookie:SS=Q0=5Lb_nQ; path=/search
      ETag:VV/"7777-1242234904000"        (缓存相关的,可以做到时时更新)
      Expires:-1          (通知客户端将回送的数据资源缓存多长时间,-1与0表示不缓存)
      Cache-Control:no-cache      (通知客户端不缓存数据)
      Pragma:no-cache             (通知客户端不缓存数据)
      Connection:close(Keep-Alive)
      Date:Thu, 11 Aug 2016 10:55:36 GMT
      
      • 如:ServletDemo:

        package com.djh.servlet;
        import java.io.ByteArrayOutputStream;
        import java.io.IOException;
        import java.util.zip.GZIPOutputStream;
        import javax.servlet.ServletException;
        import javax.servlet.annotation.WebServlet;
        import javax.servlet.http.HttpServlet;
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        /**
         * Servlet implementation class ServletDemo
         */
        @WebServlet("/ServletDemo")
        public class ServletDemo extends HttpServlet {
            /**
             * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
             */
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                //1.create a data
                String str = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
                System.out.println("before compress :" + str.getBytes().length);
                //2.create Byte Array Output Stream
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                //3.create a GZIP stream
                GZIPOutputStream gzos = new GZIPOutputStream(baos);
                //4.start zip data
                gzos.write(str.getBytes());
                //5.close gzos and baos
                gzos.close();
                baos.close();
                byte gzip[] = baos.toByteArray();
                System.out.println("After compress : " + gzip.length);
                //设置数据的压缩格式
                response.setHeader("Content-Encoding", "gzip");
                response.setHeader("Content-Length", gzip.length + "");
                //set the refresh time,表示页面每隔5秒刷新一次
        //      response.setHeader("Refresh", 5 + "");
        //      response.setHeader("Refresh", "5; url='http://www.baidu.com'");     //表示每隔5秒刷新至百度界面
                response.setHeader("Content-Disposition", "attachment; filename='4.java'");     //设置以下载的方式打开数据,并保存文件名为4.java的文件
                //response data
                response.getOutputStream().write(gzip);
            }
            /**
             * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
             */
            protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                // TODO Auto-generated method stub
            }
        }
        
    • HTTP请求头字段:

      • Range头只是服务器只传输一部分Web资源,这个头可以用来实现断电续传功能,Range字段可以通过三种格式设置要传输的直接范围:

        Range: bytes=1000-2000  //表示传输范围从1000到2000字节
        Range: bytes=1000-      //表示传输Web资源中第1000个字节以后的所有内容
        Range: bytes=1000           //传输最后1000个字节
        
    • HTTP响应消息头字段

      • Accept-Ranges:这个字段说明web服务器是否支持Range支持,则返回Accept-Ranges: bytes;如果不支持,则返回Accept-Ranges: none
      • Content-Range:指定了返回的Web资源的直接范围,这个字段值的格式是如下:

        Content-Range: 1000-3000/5000

7、Servlet开发

  • Servlet是一门用于开发动态Web资源的技术
  • API中提供了一个servlet接口,若想开发一个动态web资源,需要完成以下2步:
    • 编写一个Java类,实现servlet接口
    • 将开发好的Java类部署到web服务器中
  • 在浏览器地址栏中输入一个地址,按下回车键所发生的事:
    • 1、浏览器拿到地址,优先访问本地的hosts文件获取对应的ip地址,若hosts中不存在时会去访问DNS,连上服务器
    • 2、与服务器建立连接,向服务器发送http请求
    • 3、web服务器根据请求的数据解析出需要访问的主机名、web应用以及web资源
    • 4、首次访问时创建servlet实例
    • 5、调用servlet的init()方法完成初始化serlet对象
    • 6、web服务器创建请求与响应,向servlet发送请求
    • 7、service()方法响应客户端的请求,并对根据请求(request)进行处理
    • 8、执行servlet的service方法,对请求进行处理
    • 9、将处理的数据通过service方法的response返回
    • 10、web服务器根据response中的数据构建一个http响应并回复客户端
    • 11、web服务器向浏览器发送http响应
    • 12、浏览器根据响应进行解析,将数据提取并显示
  • Servlet接口实现类

    • 默认两个实现类:

      GenericServlet、HttpServlet 
      
    • HttpServlet
      • HttpServlet指能够处理HTTP请求的servlet,他在原有Servlet接口上添加了一些与HTTP协议相关的处理方法
      • HttpServlet在实现Servlet接口时,覆写了service方法,改方法内的代码会自动判断用户的请求方式,然后调用相应的方法(doGet或doPost)
  • servlet的配置文件是在web.xml文件中进行的,使用servlet与servlet_mapping完成配置

    • servlet元素用于注册Servlet,其包含两个主要的子元素:servlet-name与servlet-class,分别用于设置Servlet的注册名称和Servlet的完整类名
    • 一个servlet-mapping元素用于映射一个已注册的Servlet的一个对外访问路径,其包含两个子元素:servlet-name与url-pattern,分别用于指定Servlet的注册名称和Servlet的对外访问路径,如:

      <web-app>
          <servlet>
              <servlet-name>news</servlet-name>
              <servlet-class>com.djh.cn.NewsServlet</servlet-class>
          </servlet>
          <servlet-mapping>
              <servlet-name>news</servlet-name>
              <url-pattern>/newswebapp</url-pattern>
          </servlet-mapping>
      </web-app>
      
    • 同一个Servlet可以被映射到多个URL上,也即是多个servlet-mapping元素的servlet-name子元素的设置值可以是同一个Servlet的注册名
    • 在Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式

      • 第一种格式是:“*.扩展名”

        <servlet-mapping>
            <serlet-name>AnyName</servlet-name>
            <url-pattern>*.html</url-pattern>
        </servlet-mapping>
        
      • 第二种格式:以正斜杠(/)开头并以“/*”结尾(匹配任意的)

        <servlet-mapping>
            <servlet-name>AnyName</servlet-name>
            <url-pattern>/action/*</url-pattern>
        </servlet-mapping>
        
    • Servlet不能独立运行,它的运行完全由Servlet引擎控制和调度
    • 一般情况下,Servlet只会创建一个Servlet实例对象(service的init方法调用),该对象会一直存在直至Web容器退出,才会被销毁(service的destory方法)
    • Servlet每次的访问请求,Servlet引擎都会创建一个新的HttpServletRequest对象与一个新的HttpServerResponse对象
    • 关于servlet中的子元素load-on-startup

      • 当servlet中包含改元素时表示当服务器启动时就初始化执行init方法
      • servlet-on-startup元素中的数据越小表示的优先级越高,如:

        <servlet>
            <servlet-name>AnyName</servlet>
            <servlet-class>包名+类名</servlet-class>
            <load-on-startup>2</load-on-startup>
        </servlet>
        
      • 在Struts框架中就应用到了该子元素
      • 用途:为web应用写一个InitServlet,这个servlet配置为启动时加载,为整个web应用创建必要的数据库表和数据
    • 如果某个Servlet的映射路径仅仅是一个正斜杠(/),那么这个Servlet就称为当前web应用程序的缺省Servlet

    • 所有在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,即缺省的Servlet用于处理所有其他Servlet都不处理的访问请求
    • 当访问tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet
  • Servlet线程安全
    • 当多个客户端并发访问同一Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,若service方法内访问同一资源就可能引发线程安全问题
    • Servlet实现SingleThreadModel接口,则Servlet引擎将以单线程模式来调用其service方法
    • SingleThreaModel接口中没有定义任何方法,在Servlet类的定义时直接实现SingleThreadModel接口即可
    • 对于实现SindleThreadModel接口的Servlet,Servlet引擎仍支持对Servlet的多线程并发访问,采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象
    • 注意:SingleThreadModel并不能真正意义上解决线程安全问题,建议使用synchronized
  • Servlet配置:

    • ServletConfig对象

      • 在Servlet的配置文件中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数,如:

        <servlet>
            <init-param>
                <param-name>data</param>
                <param-value>djh</param-value>
            </init-param>
            <init-param>
                <param-name>charset</param>
                <param-value>utf-8</param-value>
            </init-param>
            <init-param>
                <param-name>url</param>
                <param-value>jdbc:mysql://localhost:3306/java</param-value>
            </init-param>
            ...
        </servlet>
        
      • web容器在创建servlet实例对象时,会自动将初始化参数封装到Servlet对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet,在doGet或doPost方法中可以获取配置对象,如:

        public class ServletDemo1 extends HttpServlet {
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                // TODO Auto-generated method stub
                //get the single parameter value 
                String val = this.getServletConfig().getInitParameter("user");
                System.out.println(val);
        
                //get the all parameter value
                Enumeration enu = this.getServletConfig().getInitParameterNames();
                while(enu.hasMoreElements()){
                    String name = (String) enu.nextElement();
                    String value = this.getServletConfig().getInitParameter(name);
                    System.out.println(name + ": " + value);
                }
                response.getOutputStream().write("<h2 style='color:blue'>Success</h2>".getBytes());
            }
        }
        
    • ServletContext对象

      • Web服务器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前WEB应用
      • ServletContext对象可以通过getServletConfig().getServletContext()方法获得
      • 一个WEB应用中的所有Servlet共享同一个ServletContext对象,Servlet对象之间可以通过ServletContext对象来实现通讯或数据共享,也即是WEB应用之间的数据通讯,如:

        //先运行ServletDemo2应用,再运行ServletDemo3应用
        public class ServletDemo2 extends HttpServlet {
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                // TODO Auto-generated method stub
                String str = "djh";
                this.getServletContext().setAttribute("data", str);
            }
        }   
        
        public class ServletDemo3 extends HttpServlet {
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                // TODO Auto-generated method stub
                String str = (String) this.getServletContext().getAttribute("data");
                System.out.println(str);        //djh
            }
        }
        
      • Servlet转发技术,getRequestDispatcher()方法,如:

        public class ServletDemo4 extends HttpServlet {
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                // TODO Auto-generated method stub
                String str = "This is Servlet forward technology";
        
                //使用getServletContext传递数据,不建议使用,会存在线程安全问题,建议使用request域
                this.getServletContext().setAttribute("data", str);
        
                //Servlet转发技术,获取转发对象
                RequestDispatcher rd = this.getServletContext().getRequestDispatcher("/1.jsp");
                //转发
                rd.forward(request, response);
            }
        }
        
        1.jsp:
        <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
        <html>
        <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Insert title here</title>
        </head>
        <body>
        
            <font style="color:green; font-family:consolas;">
            <%
                //在JSP中,使用application代表context,如下:
                String data = (String)application.getAttribute("data");
                out.write(data);
            %>
            </font>
        </body>
        </html>
        
      • ServletContext对象读取资源文件

        • 读取资源的方式:

          • 方式一:getResourceAsStream()方法

            • 从properties文件中读取,使用getResourceAsStream(path)方法

              1、当properties文件在src目录下时,path的值为:
                  /WEB_INF/classes/文件名.properties
              2、当文件在包名下时,path的值为:
                  /WEB-INF/classes/包名转变的路径名/文件名.properties
                  如:在包名com.djh下的db.properties
                      /WEB-INF/classes/com/djh/db.properties
              3、当文件直接在web应用路径下时,path值为:
                  /WEB-INF/文件名.properties
              
            • 在WEB应用中不要直接使用FileInputStream读取资源文件
          • 方式二,使用FileInputStream绝对路径的方式读取

            • 获取资源文件的绝对路径:

              String path = this.getServletContext().getRealPath(path);   //path的值即是方式一中的path值
              
            • 使用文件流读取

              FileInputStream fis = new FileInPutStream(path);
              
            • 使用properties的方式读取资源文件

              Properties pros = new Properties();
              pros.load(fis);
              String str1 = pros.getProperty("name");
              ......
              
          • 方式三,通过类装载器的形式

            • 使用类装载器的getResource()方法获取文件资源URL,再通过getPath()方法获取绝对路径

              String path = 类.class.getCalssLoader().getResoource("资源文件路径").getPath();
              
            • 通过传统读文件方式FileInputStream读取资源文件

              FileInputStream fis = new FileInPutStream(path);
              
          • 对于读取资源文件,如果只要读取一次,在多处应用时,一般使用静态代码块来处理这部分操作
          • 通过类的加载器来读取的文件不能太大
  • response与request对象:

    • HttpServletResponse:

      • 这个对象中封装了向客户端发送数据、发送响应头、发送响应码的方法
      • 方法:

        setStatus(int sc)、setHeader(String name, String value)、getWriter()、getOutputStream()    
        
    • response常见应用

      • 向客户端输出中文数据(使用OutputStream输出1时,用户看到的不是1)

        public class ServletDemo1 extends HttpServlet {
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                // TODO Auto-generated method stub
                response.setHeader("Content-type", "text/html;charset=UTF-8");          //设置客户端以什么编码打开,写错时,浏览器会提示以下载的形式打开
        
                String data = "这是中文字符使用字节流输出";
                //获取输出字节流
                OutputStream os = response.getOutputStream();
                //向response写入数据
                os.write(data.getBytes("UTF-8"));       //带参表示以什么编码形式写入
        
            }
        }
        
        • html中的标签可以模拟一个http响应头,可以控制浏览器的行为
        • 使用字符流时注意编码格式为,可以使用如下方式更改编码格式

          response.setCharacterEncoding("utf-8");     //设置response使用的码表
          
      • 文件下载和中文文件的下载

        • 如果下载的文件为中文文件名,则文件名需要经过url编码,如:

          response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encoder(filename, "UTF-8"));
          
      • 输出随机图片(BufferedImage、ImageIO),如:验证码的应用

        • 汉字在Unicode中的区间:汉字区间:0x4E00→0x9FA5(Unicode码表)(\u4e00-\u9fa5)

          //构建图片
          BufferedImage image= new BufferedImage(wdth, height, BufferedImage.TYPE_INT_RGB);
          //获取图形对象
          Graphics graph = image.getGraphicas();
          
          //设置背景色
          setBackGround(graph);
          setBorder(graph);           //设置边框
          drawRandomLine(graph);      //画随机线
          drawRandomNum((Graphics2D)graph);       //写随机数
          response.setContentType("image/jpeg");
          response.setHeader("expries", -1);      //设置浏览器不缓存
          response.setHeader("Cache-Control", "no-cache");
          response.setHeader("Pragma", "no-cache");
          ImageIO.write(image, "jpg", response.getOutputStream());        //向response写入图片数据
          
          private void setBackground(Graphics g){
              g.setColor(Color.WHITE);
              g.fillRect(width,height);
          }
          private void setBorder(Graphics g){
              g.setColor(Color.BLUE);
              g.drawRect(xpos, ypos, width-2*xpos, height-2*ypos);
          }
          private void drawRandomLine(Graphics g){
              g.setColor(Color.GREEN);
              for(int i = 0; i = count; i++){     /count表示画多少条线
                  //设置线的起始坐标
                  int Xstart = new Random().nextInt(width);
                  int Ystart = new Random().nextInt(height);
                  //设置线的终点坐标
                  int Xend = new Random().nextInt(width);
                  int Yend = new Random().nextInt(height);
                  g.drawLine(Xstart, Ystart, Xend, Yend);
              }
          }
          
          private void drawRandomNum(Graphics2D g){
              g.setColor(Color.BLACK);
              g.setFont(new Font("consolas", Font.BOLD, font_size));
              for(int i = 0; i < cnt; i++){
                  //汉字区间:0x4E00→0x9FA5(Unicode码表)(\u4e00-\u9fa5)
                  int degree = new Random.nextInt()%30;   //表示-30与30度以内的旋转
                  String str = "常用汉字码表";
                  String fnt = str.charAt(new Random().nextInt(str.length())) + "";
                  //调用Graphics2D的rotate()方法旋转字体
                  g.rotate(degree*Math.PI/180, , font_size);
                  g.drawString(fnt, i + 5 + (i*(font_size + 10)), font_size);     //加5表示距边框一段距离
                  g.rotate(-degree*Math.PI/180, , font_size)  
              }
          }
          
      • 发送http头,控制浏览器定时刷新网页(refresh)

        • 设置refresh头属性,如:

          response.setHeader("refresh", "5"); //5秒刷新一次
          response.setHeader("refresh", "5;url='URL地址'"); //表示5秒后将跳转至url所指向的地址页面
          
      • 发送http头,控制浏览器禁止缓存当前文档内容(expires),如:

        response.setHeader("expires", System.currentTimeMillis() + 1000*60);    //表示保存一分钟的数据,一分钟之后重新发请求 
        
      • 通过response实现请求重定向:(注意转发与重定向的场合)

        • 请求重定向:指一个web资源收到客户端请求后,通知客户端去访问另外一个web资源
        • 应用场景:用户登录、购物车...
        • 实现方式:

          • response.sendRedirect(location)
          • 如:

            response.sendRedirect("/news/index.jsp");
            //相当于:
            //response.setStatus(302);
            //response.setHeader("location", "/news/index.jsp");
            
        • 实现原理:
          • 302状态码和location头即可实现重定向
        • 重定向特点:
          • 浏览器会向服务器发送两次,即有两个request与response
          • 重定向技术会使浏览器地址栏发生变化
      • getOutputStream与getWrite方法互斥,调用其中任意一个方法后,就不能在调用另一个方法
    • HttpServletRequest:

      • 代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中
      • 获取客户机信息方法:

        • getRequestURL:返回客户端发出请求时的完整URL,如:

          http://www.sina.com/news/1.html
          
        • getRequestURI:返回请求行中的资源名部分,如:

          news/1.html
          
        • getQueryString:返回请求行中的参数部分
        • getRemoteAddr:返回请求的客户端IP地址
        • getRemoteHost:返回请求客户机的的完整主机名
        • getRemotePort:返回客户端使用的网络端口号
        • getLocalAddr:返回WEB服务器的IP地址
        • getMethod:得到客户机请求方式
      • 对于中文数据的提交需要先编码,后提交(在获取数据之前,设置请求的编码格式),如:

        request.setCharacterEncoding("utf-8");      //针对于POST提交有效
        //对于GET方式的提交,可以使用反向ISO-8859-1查找,如:
        username = request.getParameter("username");
        username= new String(username.getBytes("iso8859-1"), "utf-8";
        
      • request常见应用

        • request对象实现请求转发:请求转发指一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理
        • 请求转发的应用场景:MVC设计模式
        • request对象提供一个getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发
        • request对象同时也是一个域对象,,通过request对象实现转发时,把数据通过request对象带给其他web资源处理
        • 方法:

          setAttribute、getAttribute、removeAttribute、getAttributeNames
          

          -MVC设计模式:

          M:model(JavaBean)
          V:view(JSP)
          C:control(Servlet)
          
        • 转发注意事项:
          • forward用于将请求转发到RequestDispatcher对象封装的资源
          • 客户端只发一次请求,而服务器端有多个资源调用
          • 浏览器地址栏无变化
        • include方法:

          • RequestDispatcher.include方法用于将RequestDispatcher对象封装的资源内容作为当前响应内容的一部分包含进来,从而实现可编程的服务器端包含功能
          • 被包含的Servlet程序不可能改变响应消息的状态码和响应头,如果它里面存在这样的语句,这些语句的执行结果将被忽略
          • 如:

                protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                    // TODO Auto-generated method stub
                    String data = "this is middle text<br/>";
                    request.getRequestDispatcher("/page/1.jsp").include(request, response);
                    request.setAttribute("data", data);
                    request.getRequestDispatcher("index.jsp").include(request, response);
                    request.getRequestDispatcher("/page/2.jsp").include(request, response);
                }
            
                //1.jsp
                <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
                    pageEncoding="ISO-8859-1"%>
                <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
                <html>
                <head>
                <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
                <title>Insert title here</title>
                </head>
                <body>
                    This is first JSP file.<br />
                //index.jsp
                    <%
                        String data = (String)request.getAttribute("data");
                        out.write(data);
                    %>
                //2.jsp
                    This is Second JSP file.<br />
                    </body>
                    </html>
            
      • 防盗链
      • request各种表单输入项数据的获取:
      • text、password、radio、checkbox、file、select、textarea、hidden、image、button给js编程用
      • 请求参数的中文乱码问题
      • URL地址的编码
    • 需要用到地址(path)的:
      • getRequestDispatcher(path)
      • response.sendRedirect(path)
      • getServletContext().getRealPath(path)
      • getServletContext().getResourceAsStream(path)
      • form表单的action属性值
      • a标签的href属性值

8、Cookie与Session

  • 会话
    • 多用户访问服务器时,产生的数据,需要保存每个用户的数据
  • 保存会话数据的两种技术:

    • Cookie:

      • Cookie是客户端技术,程序将每个用户的数据以Cookie的形式写给用户各自的浏览器,当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去,这就确保了web资源处理的就是用户各自的数据。
      • Cookie API

        • javax.servlet.http.Cookie类用于创建一个Cookie,response接口中也定义了一个addCookie方法,用于在其响应头中增加一个相应的Set-Cookie头字段。request接口中也定义了一个getCookie方法,用于获取客户端提交的Cookie.
        • Cookie类的方法:
          • public Cookie(String name, String value)
          • setValue与getValue
          • setMaxAge与getMaxAge(方法为设置Cookie的有效期,默认客户端进程关闭)
          • setPath与getPath
          • setDomain与getDomain
          • getName
        • Cookie应用:

          public class CookieDemo1 extends HttpServlet {
              /**
               * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
               *
               * 测试cookie,使用浏览器上次访问时间的例子
               */
              protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          
                  //1.设置响应数据的编码格式
                  response.setCharacterEncoding("UTF-8");
                  //2、设置浏览器打开的编码格式
                  response.setContentType("text/html;charset=UTF-8");
                  //3、获取响应流
                  PrintWriter pw = response.getWriter();
                  //4、获取Cookies数组
                   Cookie[]  cookies = request.getCookies();
                   //5、先判断Cookie是否含有Cookie,有则遍历Cookies数组,获取相应的Cookie,否则不执行
                   if(cookies != null){
                       for(int i = 0; i <cookies.length; i++){
                           //6、获取相应的Cookie
                          if(cookies[i].getName().equals("localAccessTime")){
                              long time =Long.parseLong(cookies[i].getValue());
                              //7、将long型的毫秒数转换成日期字符串
                              String date = new Date(time).toLocaleString();
                              //8、向浏览器发送的数据
                              String data = "上次访问 浏览器的时间: ";
                              pw.print(data + date);
                          } 
                       }
                   }
          
                   //9、创建Cookie对象,并封装最新的访问时间
                   Cookie cookie = new Cookie("localAccessTime", System.currentTimeMillis()+"");
                   //10、设置Cookie的有效时间,默认是浏览器关闭即被删除,以秒为单位,注意:0表示删除Cookie文件
                   cookie.setMaxAge(5*24*60*60);
                   //11、设置访问客户端携带Cookie的路径
                   cookie.setPath("/itheima");
                   //12.向浏览器(客户端)发送最新的Cookie
                   response.addCookie(cookie);
              }
          }
          
        • Cookie细节:
          • 一个Cookie只能标识一种信息,至少含有一个标识该信息的名称(name)与设置值(value)
          • 一个WEB站点可以给一个WEB浏览器(客户端)发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie
          • 浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB
          • 注意:删除Cookie时,path必须保持一致,否则不会删除
    • Session:

      • Session是服务端技术,利用该技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其他web资源时,其他web资源再从用户各自的session中取出数据为用户服务。
      • 在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务
      • Session和Cookie的主要区别在于:
        • Cookie是把用户的数据写给用户的浏览器
        • Session技术把用户的数据写到用户独占的session中
      • Session对象由服务器创建,可以调用request对象的getSession方法得到session对象
      • Session是基于Cookie的,如下:

        //session创建时,会创建一个相应的Cookie,并回写给客户端
        HttpSession session = request.getSession();
        String sessionId = session.getId();
        Cookie cookie = new Cookie("JSESSIONID", sessionId);    //通过session创建的Cookie的名字为JSESSIONID
        //Cookie可以设置有效期
        cookie.setMaxAge(time);         //time表示的是多少秒
        response.addCookie(cookie);     //回写Cookie
        
      • 使用response的encodeURL方法可以设置url,会在url后自动添加jsessionid,如:

        String url = response.encodeURL("webappurl");
        
      • session案例:
        • 用户登录
        • 防止表单重复提交
          • 表单页面由servlet程序生成,通过servlet为每次产生的表单页面分配一个唯一的随机标识符,并在form表单的一个隐藏字段中设置这个标识符,并将标识符保存在当前的session中
        • 实现一次性验证码
    • 基本的三个域对象(容器):
      • request
        • 当数据显示完就无用时,可以采用request
      • session
        • 数据除了显示,另外的一段时间内还有用,使用session
      • servletContext
        • 数据除了当前的servlet需要用到还需要另外的servlet用到

猜你喜欢

转载自blog.csdn.net/djh_happy/article/details/52504680