必威体育Betway必威体育官网
当前位置:首页 > IT技术

Java Web编程

时间:2019-09-30 00:14:28来源:IT技术作者:seo实验室小编阅读:75次「手机版」
 

web编程

一.Servlet

1.requestDispatcher

RequestDispatcher是一个接口,它包含两个方法:forward(request, response)和

include(request, response)。RequestDispatcher 有一个特点,就是浏览器上显示

的URL是最先请求的目标资源的URL,不会因为使用了forward、include方法而改

变。因此forward和include的调用对于用户来说是透明的。

(1)forward

       这个方法将请求从一个 Servlet or JSP目标资源 上 转发到服务器上的另一个

       资源(servlet、JSP 文件或 HTML 文件,这些资源必须是当前Web上下文中

       的),让其它的资源去生成响应数据。如下图中的,用户请求的是目标资源

       servlet1,servlet1接受到请求后,转发到servlet2,真正产生响应数据是

       servlet2,而servlet1只是起个引导转发作用。浏览器的地址栏不会变,依然

       是servlet1的URL。 

        

       注意点:

     (a)在目标资源中调用forward方法时,必须保证此响应没有提交。也就是不

              要使用 ServletResponse 对象的输出流对象,因为即便你写入了数据到

              响应缓冲区,最后也会被清空,如果缓冲区数据被刷新提交(out.flush),

              还会抛出IllegalStateException异常。

     (b)对于forward方法传递的request对象:虽然我们从调用上看,好像是将

              request对象传递给转动的资源上去了,但是我发现目标资源使用的

              request对象和转发的资源使用的request对象不是同一个request对象,

              因为分别从这2个request中获取RequestURL,发现是不一样的。但是

              在目标资源request提取的Paramter 和 Attribute   ,在转发后的资源的

              request对象中,依然都可以提取到,且是相同的。所以,二者只是在

              请求路径相关的属性上不同,其它API调用返回的都是一样的。

     (c)在forward语句的前后,都不应该有响应输出的语句,应该会被忽略。

       ServletRequest接口的getRequestDispatcher()方法返回

       RequestDispatcher的对象。句法:

RequestDispatcher requestDispatcher = request.getRequestDispatcher("/sessionLoginDemo/login.jsp");//得到转发器


requestDispatcher.forward(request, response);//转发(调度)请求给/sessionLoginDemo/login.jsp 并由login.jsp发送response给客户端。

(2)include

      此方法用于包含响应中某个资源(servlet、JSP 页面和 HTML 文件)的内

      容。调用者指定一个被包含的资源,将这个包含的资源(JSP,Servlet,

      HTML)的响应数据包含到自己的响应体中。被包含的数据是在服务器上经

      过运行产生的,因此是动态包含而不同于JSP中的include指令,它是

            JSP转译期的静态包含。这个过程实质是用一个相同的Request再请求

      一次被包含的资源,将被包含的资源的响应数据包含到原本的资源中去,

      构成它的响应数据的一部分。

      

2.response.sendredirect

示例:response.sendRedirect("login.jsp");

使用response.sendRedirect传递参数:

response.sendRedirect("/UsersManager/MainFrame?uname="+username+"&pwd="+password);

3.RequestDispatcher.forward和response.sendRedirect的区别:

(1)response.sendRedirect相当于浏览器接收到了响应之后又向服务器发送

      了一次请求,所以相当于两次请求。RequestDispatcher.forward相当于

      方法调用,在执行当前文件的过程中转向执行目标文件,两个文件(当

      前文件和目标文件)属于同一次请求,最本质的特点就是两次请求共享

      了reques对象和response对象。

(2)地址栏不同:response.sendRedirect方式下用户在浏览器地址栏中看

      到的是目标文件的地址,RequestDispatcher.forward方式下用户在浏览

      器地址栏中看到的是当前文件的地址。

4.java web的四大作用域

(1)Pagecontext域:作用范围是整个JSP页面,是四大作用域中最小的一

                                  个;生命周期是当对JSP的请求时开始,当响应结束

                                  时销毁。

(2)ServletRequest域:作用范围是整个请求链(请求转发也存在);生命

                                      周期是在service方法调用前由服务器创建,传入

                                      service方法。整个请求结束,request生命结束。

                                      线程安全

(3)HttpSession域:作用范围是一次会话。生命周期是在第一次调用

                                 request.getSession()方法时,服务器会检查是否已经

                                 有对应的session,如果没有就在内存中创建一个

                                 session并返回。当一段时间内session没有被使用

                               (默认为30分钟),则服务器会销毁该session。如果

                                 服务器非正常关闭(强行关闭),没有到期的session

                                 也会跟着销毁。如果调用session提供的invalidate(),

                                 可以立即销毁session。线程不安全

                                 session销毁的方式:

                               (a)超时(一般服务器设置超时时间为30分钟)服务器会销毁

                                        session;

                               (b)点击控制台的红色按钮异常关闭服务器要销毁session

                               (c)手动调用session的invalidate方法session.invalidate();

                                 注意:服务器正常关闭不销毁session,session会存到我

                                            们的硬盘中,也就是我们正常的点击stop server()会在

                                            tomcat的work的Catalina\localhost\项目名称下面生成

                                            一个文件SESSIONS(执行序列化),当服务器再次启动

                                            的时候会加载此文件(反序列化),倘若没有实现序列化

                                            接口(serializable)可能会报错因为序列化和反序列化会

                                            依据一个id。

                                 问:浏览器关闭后session会销毁吗?

                                 答:不会。

                                        我们知道Session是存在于服务器端的,当把浏览器关闭

                                        时,浏览器并没有向服务器发送任何请求来关闭Session,

                                        自然Session也不会被销毁,但是可以做一点努力,在所

                                        有的客户端页面里使用js的window.onclose来监视浏览器

                                        的关闭动作,然后向服务器发送一个请求来关闭Session,

                                        但是这种做法在实际的开发中也是不推荐使用的,最正常

                                        的办法。

                                 问:那么为什么当我们关闭浏览器后,就再也访问不到之前的

                                        session了呢?

                                 答:其实之前的Session一直都在服务器端,而当我们关闭浏

                                        览器时,此时的Cookie是存在于浏览器的进程中的,当浏

                                        览器关闭时,Cookie也就不存在了。其实Cookie有两种:

                                        一种是存在于浏览器的进程中;一种是存在于硬盘上。而

                                        session的Cookie是存在于浏览器的进程中,那么这种

                                        Cookie我们称为会话Cookie,当我们重新打开浏览器窗口

                                        时,之前的Cookie中存放的Sessionid已经不存在了,此时

                                        服务器从HttpServletRequest对象中没有检查到sessionid,

                                        服务器会再发送一个新的存有Sessionid的Cookie到客户端

                                        的浏览器中,此时对应的是一个新的会话,而服务器上原先

                                        的session等到它的默认时间到之后,便会自动销毁。就是

                                        不去管它,让它等到默认的时间后,自动销毁。

                                        注:当在同一个浏览器中同时打开多个标签,发送同一个请

                                               求或不同的请求,仍是同一个session;当不在同一个窗口

                                               中打开相同的浏览器时,发送请求,仍是同一个session;

                                               当使用不同的浏览器时,发送请求,即使发送相同的请

                                               求,是不同的session;当把当前某个浏览器的窗口全关闭,

                                               再打开,发起相同的请求时,就是本文所阐述的,是不同

                                               的session,但是它和session的生命周期是没有关系的。

(4)ServletContext(APPlication)域:作用范围是整个Web应用。当Web应用

                                                             被加载进容器时创建代表整个web应用

                                                             的ServletContext对象,当服务器关闭或

                                                             Web应用被移除时,ServletContext对象

                                                             跟着销毁。线程不安全

关于作用域的线程安全的详细内容,查看:

http://www.itkeyword.com/doc/903165062469129x507/Web-ServletContex-SessionRequest

6.web应用中的对象

(1)Servlet

      Servlet通常称为服务器端程序,是运行在服务器端的程序,用于处理及响

      应客户的请求。Servlet是个特殊的java类,继承于HttpServlet。客户端通常

      只有GET和POST两种请求方式,Servlet为了响应则两种请求,必须重写

      doGet()和doPost()方法。大部分时候,Servlet对于所有的请求响应都是完全

      一样的,此时只需要重写service()方法即可响应客户端的所有请求。

    (a)HttpServlet有三个方法:

             init(ServletConfig config):创建Servlet实例时,调用该方法的初始化

                                                        Servlet资源。在 Servlet 的生命期中,仅

                                                        执行一次 init()方法。它是在服务器装入

                                                        Servlet 时执行的。可以对它进行覆盖。

             service() 方法:service() 方法是 Servlet 的核心。每当一个客户请求一

                                      个HttpServlet对象,该对象的service() 方法就要被调用,

                                      而且传递给这个方法一个"请求"(ServletRequest)对象和

                                      一个"响应"(ServletResponse)对象作为参数。 在

                                      HttpServlet中已存在service() 方法。缺省的服务功能是

                                      调用与 HTTP 请求的方法相应的 do 功能。例如, 如果

                                      HTTP 请求方法为 GET,则缺省情况下调用 doGet() ;

                                      HTTP请求方法为POST,则缺省情况下调用doPost()。

                                      Servlet 应该为 Servlet 支持的 HTTP方法覆盖 do 功能。

                                      因为 HttpServlet.service() 方法会检查请求方法是否调用

                                      了适当的处理方法,不必要覆盖 service() 方法。只需覆

                                      盖相应的 do 方法就可以了。

             destroy() 方法:destroy() 方法仅执行一次,即在服务器停止且卸装

                                       Servlet时执行该方法。典型的,将 Servlet 作为服务器

                                       进程的一部分来关闭。可以对它进行覆盖。

    (b)Servlet的响应

             Servlet的响应可以是下列几种类型: 

             一个输出流,浏览器根据它的内容类型(如text/HTML)进行解释。 

             一个HTTP错误响应, 重定向到另一个URL、servlet、JSP。 

    (c)Servlet的生命周期

           (i)创建Servlet实例。

                   创建Servlet实例有两个时机:

                          第一个时机:客户端第一次请求某个Servlet时,系统创建该

                                                Servlet的实例。

                          第二个时机:Web应用启动时立即创建Servlet实例,即

                                                load-on-start Servlet。

                   load-on-start:

                           load-on-startup标记容器是否在启动的时候实例化并调用其

                           init()方法的优先级。它的值表示  servlet应该被载入的顺序。

                           当值为0或者大于0时,表示容器在应用启动时就加载并初始

                           化这个servlet。如果值小于0或未指定时,则表示只有在第一

                           次请求的容器才在该servlet调用初始化函数。正值越小

                           servlet的优先级越高,应用启动时就越先加载。值相同时,

                           容器就会自己选择顺序来加载。

           (ii)Web容器调用Servlet的init()方法,对Servlet进行初始化。

           (iii)Servlet初始化后,将一直存在于容器中,用于响应客户端请求,如

                    果客户端发送GET请求,容器调用Servlet的doGet()方法处理并响应

                    请求;如果客户端发送POST请求,容器调用Servlet的doPost()方法

                    处理并响应请求。或者统一使用service()方法处理来响应用户请求。

           (iv)Web容器决定销毁Servlet时,先调用Servlet的destory()方法,通常

                     在关闭Web应用时销毁Servlet实例。

    (d)Servlet的线程安全

           (i)对象分为有状态的对象和无状态的对象

                   有状态的对象:有数据存储功能,即有实例变量;

                   无状态的对象:无数据存储功能,即无实例变量。

             Servlet是一个单例模式,是否线程安全即取决于它的实现是有状态的

             Servlet还是无状态的Servlet。传统的实现方式,即实现HttpServlet为

             有状态的Servlet,所以非线程安全,它的线程安全问题如下:

                    静态变量:非线程安全

                    实例变量:非线程安全

                    局部变量:线程安全

             如果Servlet是实现SingleThreadModel接口,它就是无状态的,即线

             程安全。

(1)ServletContext(application)

      官方叫servlet上下文,ServletContext是一个web应用的上下文,服务器会为

      每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局

      唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共

      享对象。它是一个全局信息的存储空间,代表当前web应用。

    (a)创建和销毁

             ServletContext在web应用(服务器)启动时创建,ServletContext在Web

             应用(服务器)关闭时释放。

    (b)如何获取ServletContext

           (i)调用ServletConfig类的getServletContext()方法

                   在init(ServletConfig config)方法中,使用

                   ServletContext context=config.getServletContext();

           (ii)调用GenericServlet类的getServletContext()方法

                    其实这种方式也是调用ServletConfig类的getServletContext()方法,

                    因为GenericServlet类实现了ServletConfig接口;

           (iii)调用HttpSession类的getServletContext()方法

           (iv)ServletContextEvent类只有一个方法,就是getServletContext()

(2)ServletContextListener和ServletContextEvent

      当Servlet 容器启动或终止Web 应用时,会触发ServletContextEvent 事件,该

      事件由ServletContextListener 来处理。在 ServletContextListener 接口中定义

      了处理ServletContextEvent 事件的两个方法。

/**
 * 当Servlet 容器启动Web 应用时调用该方法。在调用完该方法之后,容器再对Filter 初始化,
 * 并且对那些在Web 应用启动时就需要被初始化的Servlet 进行初始化。
 */
contextInitialized(ServletContextEvent sce) 


/**
 * 当Servlet 容器终止Web 应用时调用该方法。在调用该方法之前,容器会先销毁所有的Servlet 和Filter 过滤器。
 */
contextDestroyed(ServletContextEvent sce)

      下面展示三个例子:

      例一,在服务启动时,将数据库中的数据加载进内存,并将其赋值给一个属性

                 名,其它的 Servlet 就可以通过 getAttribute 进行属性值的访问。包括两

                 个步骤:

                (i)实现 servletContextListerner 接口 并将要共享的通过

                        setAttribute ( name,data )方法提交到内存中去;

                (ii)应用项目通过 getAttribute(name) 将数据取到 。

                 Java代码

public class ServletContextLTest implements ServletContextListener{ 

    // 实现其中的销毁函数
    
    public void contextDestroyed(ServletContextEvent sce) { 

        System.out.println("this is last destroyeed");    

    } 

    // 实现其中的初始化函数,当有事件发生时即触发

    public void contextInitialized(ServletContextEvent sce) { 

        ServletContext sct=sce.getServletContext(); 

        Map<integer,String> depts=new HashMap<Integer,String>(); 

        Connection connection=null; 

        Preparedstatement pstm=null; 

        ResultSet rs=null; 

         

        try{ 

            connection=ConnectTool.getConnection(); 

            String sql="select deptNo,dname from dept"; 

            pstm=connection.preparestatement(sql); 

            rs=pstm.executequery(); 

            while(rs.next()){ 

                depts.put(rs.getInt(1), rs.getString(2)); 

            } 

            // 将所取到的值存放到一个属性键值对中

            sct.setAttribute("dept", depts); 

            System.out.println("======listener test is beginning========="); 

        }catch(Exception e){ 

            e.printstacktrace(); 

        }finally{ 

            ConnectTool.releasersc(rs, pstm, connection); 

        } 

    } 

}

                 在完成上述编码后,仍需在 web.xml 中进行如下配置,以使得该监听器可以起作用。                         

                 web.xml代码:

<listener>  
   <listener-class>ServletContextTest.ServletContextLTest</listener-class> 
</listener>

                 在完成上述配置后, web 服务器在启动时,会直接加载该监听器,通过以下的应用

                 程序就可以进行数据的访问。

      例二,启动线程

public class DSAction extends Thread implements ServletContextListener {

    public void contextInitialized(ServletContextEvent arg0) {
        
        super.start();// 启动一个线程
    }
    public void zdfs() throws IOException {

        Huoquzhuye u = new Huoquzhuye();// 爬虫方法类
        Htmlneirong h = new Htmlneirong();// 存入数据库类
        List<String> list = u.seturl("http://xxxxxxx");
        for (int i = 0; i < list.size(); i++) {
            String txt = list.get(i).substring(0, 22);
            String start = list.get(i).substring(4, 14);
            String end = list.get(i).substring(22, list.get(i).length());
            try {
                h.seturl(txt, start, end);
            } catch (ClassnotfoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SQLException e) {

                e.printStackTrace();
            }
        }

    }

    @Override
    public void run() {
        while (true) {
            try {
                this.zdfs();
                super.sleep(1000 * 60 * 10);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.
     * ServletContextEvent)
     */


    /*
     * (non-Javadoc)
     * 
     * @see
     * javax.servlet.ServletContextListener#contextInitialized(javax.servlet
     * .ServletContextEvent)
     */

    public void contextDestroyed(ServletContextEvent arg0) {
        super.stop();// 停止线程

    }
}

                 web.xml代码

<listener>
   <listener-class>bj.hbj.dingshi.DSAction</listener-class>
</listener>

      (i)调用super.start()开启线程。

      (ii)最后关闭线程super.stop()。

7.web.xml

(1)web.xml的加载顺序:

      ServletContext -> context-param(无顺序)-> listener(无顺序)-> filter(书写顺序)

      -> servlet(load-on-startup优先级)

      详细步骤如下:

    (i)启动一个web项目,web容器(如tomcat)读取web.xml文件,读取其中的配置信

            息。

    (ii)容器创建一个servlet上下文(servletContext),这个web项目所有部分共享这个

            上下文。

    (iii)容器将<context-param>转换为键值对,交给servletContext

    (iv)容器创建<listener>中的监听器实例

    (v)触发contextInitialized方法,listener被调用(当Servlet 容器启动或终止Web 应

             用时,会触发ServletContextEvent 事件,该事件由ServletContextListener 来

             处理。在 ServletContextListener 接口中定义了处理ServletContextEvent 事件

             的两个方法contextInitialized和contextDestroyed,web.xml有

             contextloaderlistener监听器,Spring框架实现了本监听器的接口方法)调

             用完contextInitialized方法后,容器再对filter初始化。

             ContextLoaderListener:Spring实现的类,它继承自ContextLoader,并且实

                                                     现ServletContextListener接口(实现了

                                                     contextInitialized和contextDestroyed,这是它的核

                                                     心功能)。详细查看:

                                                     https://blog.csdn.net/qq_15037231/article/details/78743765

    (vi)容器对web.xml中的指定load-on-startup的值为正数Servlet初始化

            (优先级1,2,3...->递减),负数或不指定则在该Servlet调用时初始化

              (springMVC的初始化为此阶段)

(2)web.xml文件中配置<context-param>和<init-param>的区别

      <context-param>和<init-param>都是上下文参数,但它们的范围和使用方式不同。

      <context-param>是application范围内的初始化参数,用于向servlet-context提供键

      值对,即应用程序的上下文信息,listener、filter等初始化时会用到这些信息。

      <init-param>是servlet范围内的参数,只能在servlet类的init()方法中取得。

      示例如下:

<context-param>  
           <param-name>context/param</param-name>  
           <param-value>avalible during application</param-value>  
</context-param>
 <servlet>
    <servlet-name>ReadContext</servlet-name>
    <servlet-class>file.ReadContext</servlet-class>
    <init-param>
        <param-name>user1</param-name>
        <param-value>user1-ps</param-value>
    </init-param>
  </servlet>

(3)<session-config></session-config>

      <session-config> 用于设置容器的session参数,比如:<session-timeout> 用于指

      定http session的失效时间,-1 代表session永远不会过期。

(4)<listener></listener>

     (a)listener介绍

              <listener>为web应用程序定义监听器,监听器用来监听各种事件,比如:

              application和session事件,所有的监听器按照相同的方式定义,功能取决去

              它们各自实现的接口,常用的Web事件接口有如下几个:

            (i)ServletContextListener:用于监听Web应用的启动和关闭;

            (ii)ServletContextAttributeListener:用于监听ServletContext范围

                    (application)内属性的改变;

            (iii)ServletRequestListener:用于监听用户的请求;

            (iv)ServletRequestAttributeListener:用于监听ServletRequest范围

                    (request)内属性的改变;

            (v)HttpSessionListener:用于监听用户session的开始和结束;

            (vi)HttpSessionAttributeListener:用于监听HttpSession范围(session)

                      内属性的改变。

              <listener>主要用于监听Web应用事件,其中有两个比较重要的WEB应用

              事件:应用的启动和停止(starting up or shutting down)和Session的创

              建和失效(created or destroyed)。应用启动事件发生在应用第一次被

              Servlet容器装载和启动的时候;停止事件发生在Web应用停止的时候。

              Session创建事件发生在每次一个新的session创建的时候,类似地

              Session失效事件发生在每次一个Session失效的时候。为了使用这些

              Web应用事件做些有用的事情,我们必须创建和使用一些特殊的“监听

              类”。它们是实现了以下两个接口中任何一个接口的简单java类:

              javax.servlet.ServletContextListener或

              javax.servlet.http.HttpSessionListener,如果想让你的类监听应用的启动

              和停止事件,你就得实现ServletContextListener接口;想让你的类去监

              听Session的创建和失效事件,那你就得实现HttpSessionListener接口。

     (b)Listener配置

              配置Listener只要向Web应用注册Listener实现类即可,无序配置参数之

              类的东西,因为Listener获取的是Web应用ServletContext(application)

              的配置参数。为Web应用配置Listener的两种方式:

            (i)使用@WebListener修饰Listener实现类即可。

            (ii)在web.xml文档中使用<listener>进行配置。

              注意:6中的(2)是只针对ServletContextEvent配置的一个Listener。

              web.xml的方式如下所示:


<listener>  
   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
</listener>

(5)<filter></filter>

      

二.Jsp

1.Forward和Redirect

Forward和Redirect代表了两种请求转发方式:直接转发和间接转发。

直接转发方式(Forward):客户端和浏览器只发出一次请求,Servlet、

                                             HTML、JSP或其它信息资源,由第二个信息资

                                             源响应该请求,在请求对象request中,保存的

                                             对象对于每个信息资源是共享的。

间接转发方式(Redirect):实际是两次HTTP请求,服务器端在响应第一

                                             次请求的时候,让浏览器再向另外一个URL发

                                             出请求,从而达到转发的目的。

2.Jsp的九个隐藏变量

(1)Request

(2)Response

(3)Session

(4)application

(5)out

(6)config

      javax.servlet.ServletConfig实例化对象,我们也可以在web.xml文件中配置

      JSP,只是很少用。

(7)page

      翻译成Servlet后相当于this

(8)PageContext

      参看:http://www.cnblogs.com/fjdingsd/p/5117303.html

(9)exception 

      exception 对象的作用是显示异常信息,只有在包含 isERRORPage="true" 的页

      面中才可以被使用,在一般的JSP页面中使用该对象将无法编译JSP文件。

      excepation对象和Java的所有对象一样,都具有系统提供的继承结构。

      exception 对象几乎定义了所有异常情况。在Java程序中,可以使用try/catch

      关键字来处理异常情况; 如果在JSP页面中出现没有捕获到的异常,就会生

      成 exception 对象,并把 exception 对象传送到在page指令中设定的错误页

      面中,然后在错误页面中处理相应的 exception 对象。

3.<%@include%>和<jsp:include>的区别

<%@include file="文件的URL"%> **静态引入**

 页面请求之前预编译,所有代码包含进来之后,一起进行处理,把所有代码合在

一起,编译成一个servlet

<jsp:include page="文件的URL"/>**动态引入**

 所有代码分别处理,在页面被请求的时候才编译,被编译成多个servlet,页面语

法相对独立,处理完成之后再将代码的显示结果(处理结果)组合进来。

三.Web应用的编码问题

1.先了解字符集和编码

(1)字符集和编码

     概念:简单的说字符集就规定了某个文字对应的二进制数字存放方式

                    (编码)和某串二进制数值代表了哪个文字(解 码)的转换关系

           我们在计算机屏幕上看到的是实体化的文字,而在计算机存储介质中存放的

     实际是二进制的比特流。那 么在这两者之间的转换规则就需要一个统一的标

     准,否则把我们的u盘插到老板的电脑上,文档就乱码了;小伙伴QQ上传过

     来的文件,在我们本地打开又乱码了。 于是为了实现转换标准,各种字符集

     标准就出现了。

     例如,“屌”这个字,对应的编码如下:  

字符集 16进制编码 对应的二进制数据
UTF-8 0xE5B18C 1110 0101 1011 0001 1000 1100
UTF-16 0x5C4C 1011 1000 1001 1000
GBK 0x8CC5 1000 1100 1100 0101

   (a)ASCII

            ASCII 码使用指定的 7 位或 8 位二进制数组合来表示 128 或 256 种可能

            的字符。标准 ASCII 码也叫基础ASCII码,使用 7 位二进制数来表示所有

            的大写和小写字母,数字 0 到 9、标点符号, 以及在美式英语中使用的

            特殊控制字符。

   (b)非ASCII编码

            英语用128个符号编码就够了,但是用来表示其他语言,128个符号是不够

            的。比如,在法语中,字母上方有注音符号,它就无法用 ASCII 码表示。

            于是,一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号。比

            如,法语中的é的编码为130(二进制10000010)。这样一来,这些欧洲

            国家使用的编码体系,可以表示最多256个符号。但是,这里又出现了新

            的问题。不同的国家有不同的字母,因此,哪怕它们都使用256个符号的

            编码方式,代表的字母却不一样。比如,130在法语编码中代表了é,在希

            伯来语编码中却代表了字母Gimel (ג),在俄语编码中又会代表另一个符号。

            但是不管怎样,所有这些编码方式中,0--127表示的符号是一样的,不一

            样的只是128--255的这一段。至于亚洲国家的文字,使用的符号就更多了,

            汉字就多达10万左右。一个字节只能表示256种符号,肯定是不够的,就必

            须使用多个字节表达一个符号。比如,简体中文常见的编码方式是gb2312

            使用两个字节表示一个汉字,所以理论上最多可以表示 256 x 256 = 65536

            个符号。

   (c)unicode

            正如上一节所说,世界上存在着多种编码方式,同一个二进制数字可以被

            解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码

            方式,否则用错误的编码方式解读,就会出现乱码。为什么电子邮件常常

            出现乱码?就是因为发信人和收信人使用的编码方式不一样。以想象,如

            果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个

            独一无二的编码,那么乱码问题就会消失。这就是 Unicode,就像它的名

            字都表示的,这是一种所有符号的编码。Unicode 当然是一个很大的集合,

            现在的规模可以容纳100多万个符号。每个符号的编码都不一样,比如,

            U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,U+4E25表

            示汉字严。具体的符号对应表,可以查询unicode.org,或者专门的汉字对

            应表。

            Unicode的问题:

                    需要注意的是,Unicode 只是一个符号集,它只规定了符号的二进制

            代码,却没有规定这个二进制代码应该如何存储。

            比如,汉字严的 Unicode 是十六进制数4E25,转换成二进制数足足有15

            位(100111000100101),也就是说,这个符号的表示至少需要2个字节。

            表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。这里就

            有两个严重的问题,第一个问题是,如何才能区别 Unicode 和 ASCII ?

            计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第

            二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果

            Unicode 统一规定,每个符号用三个或四个字节表示,那么每个英文字母

            前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件

            的大小会因此大出二三倍,这是无法接受的。它们造成的结果是:一是出

            现了 Unicode 的多种存储方式,也就是说有许多种不同的二进制格式,可

            以用来表示 Unicode。二是Unicode 在很长一段时间内无法推广,直到互

            联网的出现。

          (i)UTF-8

                   互联网的普及,强烈要求出现一种统一的编码方式。UTF-8 就是在互

                   联网上使用最广的一种 Unicode 的实现方式。其他实现方式还包括

                   UTF-16(字符用两个字节或四个字节表示)和 UTF-32(字符用四个

                   字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,

                   UTF-8 是 Unicode 的实现方式之一。UTF-8 最大的一个特点,就是它

                   是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不

                   同的符号而变化字节长度。UTF-8 的编码规则很简单,只有二条:

                   第一条:对于单字节的符号,字节的第一位设为0,后面7位为这个符

                                 号的Unicode码。因此对于英语字母,UTF-8 编码和 ASCII

                                 码是相同的。

                  第二条:对于n字节的符号(n > 1),第一个字节的前n位都设为1,第

                                 n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提

                                 及的二进制位,全部为这个符号的 Unicode 码。下表总结了编

                                 码规则,字母x表示可用编码的位。

                 总结:

                  UNICODE和UTF-8的区别:

                       UNICODE是字符集(编码),UTF-8是编码格式,编码格式是用来序列化或

                       存储字符集编码的一种“格式”。。

                  关于UNICODE和UTF-8参考自:

                  https://blog.csdn.net/Deft_MKJing/article/details/79460485

          (ii)UTF-16

                   暂时略

          (iii)UTF-32

                    暂时略

3.关于windows平台的记事本编码说明

具体参看:http://www.cnblogs.com/WestGarden/archive/2012/09/02/3138331.html

4.Java中的编码

首先强调一下“编码和编码格式”(这里有些和上面的内容重复)

Unicode是一种“编码”,所谓编码就是一个编号(数字)到字符的一种映射关系,就仅仅是一

种一对一的映射而已;GBK、UTF-8是一种“编码格式”,是用来序列化或存储1中提到的那

个“编号(数字)”的一种“格式”。

GBK和UTF-8都是用来序列化或存储Unicode编码的数据的,但是分别是2种不同的格式,

他们都是Unicode编码的实现方式;他们俩除了格式不一样之外,他们所关心的Unicode编

码范围也不一样。UTF-8考虑了很多种不同国家的字符;而GBK只考虑中文——在

Unicode中的一小部分的字符的编码。

(1)J2SE中的编码

       java的String使用的编码是Unicode,当String存在于内存中时(在代码中用string类型

       的引用对它进行操作时),是"只有编码而没有编码格式的",所以java程序中的任何

       String对象,说它是gbk还是utf-8都是错的,String在内存中不需要“编码格式”,它只

       是一个Unicode的字符串而已。

       当字符串需要在网络中传输或要被写入文件时,就需要使用编码格式了。乱码问题

       也因此出现。

     (a)Java文件编译后形成class

              这里Java文件的编码可能有多种多样,但java编译器会自动将这些编码按照

              Java文件的编码格式正确读取后产生class文件,这里的class文件编码是

              Unicode编码(具体说是UTF-16编码)。

              因此,在java代码中定义一个字符串:String s="汉字";不管在编译前java文件

              使用何种编码,在编译后成class后,他们都是一样的----Unicode编码表示。

     (b)JVM中的编码

              JVM加载class文件读取时候使用Unicode编码方式正确读取class文件,那么

              原来定义的String s="汉字";在内存中的表现形式是Unicode

(2)java web中的编码

       

       假定浏览器就是ie,WEB服务器是tomcat,页面是jsp,应用服务器用的是servlet

     (a)浏览器中打开了一个页面,这个页面映射应用服务的某个jsp。此时浏览器中

              的解码格式是什么呢?

              浏览器的解码格式是在jsp中指定的,比如在jsp文件中经常可以看到这样两

              行代码。

<!-- 
  这一句是和Tomcat说的:保存在硬盘上的jsp文件在被Tomcat翻译成servlet的时候,使用utf-8解码jsp文件的内容。
  如果不指定,会默认使用iso-8859-1来解码。
-->
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 


<!-- 这一行是和浏览器说的:浏览器解码的时候请使用utf-8解码哦 -->
<meta http-equiv="content-type" content="text/html; charset=UTF-8">

              这样浏览在解析这个jsp的时候,就是使用utf-8编码来解码。

              浏览器的解码格式也是可以在浏览器上设置的:

               

     (b)response中也可以设置内容的编码格式和指定浏览器的解码格式。

              开发人员应该都知道,jsp就是一个特殊一点的servlet。在servlet中, response

              有两个设置编码的方法,和jsp中的那两行编码配置有着相似的功能。

        // 表示response的内容会以utf-8的编码方式编码后发送给浏览器。
     response.setCharacterEncoding("UTF-8");

      // 告诉浏览器,解码的时候也要使用utf-8解码哦。
        response.setcontenttype("text/html;charset=UTF-8");

     (c)通过request对象可以指定应用服务用哪种编码格式来解码接收到的数据

    // 通过这句话,可以指定用utf-8编码格式来解码浏览器传来的数据。不过只对post方式传来的数据有效。如果是get方法传来的数据,还是会以默认的iso-8859-1来解码。
    request.setCharacterEncoding("UTF-8");

     (d)设置tomcat服务器配置文件server.xml,指定以何种编码解码浏览器传来的参

              数。

<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" URIEncoding="UTF-8" />

        

             'URIEncoding="UTF-8"', 这个属性的配置, 和"

             request.setCharacterEncoding("UTF-8");"这句代码的功能大致相同。都是指

             定tomcat服务器接受到收据后如何解码。如果不指定,tomcat服务器会默认

             使用iso-8859-1来解码。如果一个tomcat服务器里有多个应用,应该考虑该处

             修改是否会对其它应用造成伤害。

     (e)get和post传中文

             (i)get

                     方法一:在客户端使用 URLEncoder.encode(“中文”,”UTF-8”)对中文参

                                   数进行编码,在服务器端需要进行解码

                                   this.setName(java.net.URLDecoder.decode(name, “UTF-8”)); 

                     方法二:修改tomcat的server.xml文件

                              

<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8" useBodyEncodingForURI="true"/>

                     

                     其它和web中乱码的解决方案差不多。

             (ii)post

                      和web中乱码的解决方案差不多。

             乱码问题的解决来源网络,是否好使,不知道,需要自己实验一下,实验暂

             时略。

5.URL重写和重定向(这是两个比较古老的技术

(1)URL重写

    (a)概念

      URL 重写是拦截客户端传入 Web 请求URL并自动将其定向到到规则指定的 URL

      的过程。比如浏览器发来请求 http://blog.mocoder.com/hello.html ,服务器自动

    (b)URL重写的好处

           (i)搜索引擎比较喜欢.html,.htm的(与.jsp,.php,.aspx,.cff相比),因为.html,

                   .htm是静态的,更容易让引擎了解你网页的内容。而动态网页的内容是根

                   据用户,来输出不同的内容,不容易让引擎吸收具体HTML内容。

           (ii)如果不用URL Rewriting将拓展名隐藏或改成.html,那么假如这个网站

                    换个技术或把动态页面换成静态,则需要寻找所有含有拓展名的连接,

                    把连接所含URL进行拓展名修改(如从JSP换到PHP技术,则要寻找所有

                    含有.jsp的页面,并把所有含.jsp的URL改成.php,费时费力)。

                    URL Rewriting正好避免了这点,因为好的URL是能做到“不变应完变”的。

           (iii)防止某些黑客恶意攻击。

                    有些大网站采用不同的技术开发不同功能的页面。而把拓展名改掉,让黑

                    客无法确认此页面用的技术是什么,从而就无从下手。

           (iv)方便访问者使用。访问者不是程序员,他们不明白什么是.jsp,.php.aspx,

                     他们只知道URL。所以统一把拓展名拿掉,或者同意把拓展名换为html,

                     htm,有利于用户的使用。用户可以知道现在在你网站的位置,如何通过

                     输入URL到某一页面。

             url重写在php开发的web程序中应用十分广泛,当然,大多数的javaweb框架

             如springMVC、struts都有指定访问url的配置,但是不够灵活。

(2)URL重定向

      URL重定向,是指当使用者浏览某个网址时,将他导向到另一个网址的技术。

(3)重写和重定向的区别

      重定向 :浏览器知道页面位置发生变化,从而改变地址栏显示的地址。

                     搜索引擎意识到页面被移动了,从而更新搜索引擎索引,将原来失效的

                     链接从搜索结果中移除。

                     临时重定向(R=302)和永久重定向(R=301)都是亲搜索引擎的,是SEO

                     的重要技术

      重写:用于将页面映射到本站另一页面,若重写到另一网络主机域名),则按

                 重定向处理。

                 浏览器的url地址不会发生变化。

四:Web应用的安全

1.CSS攻击,跨站脚本攻击

  跨站脚本,顾名思义,就是恶意攻击者利用网站漏洞往Web页面里插入恶意代码

  一般需要以下几个条件:

(a)客户端访问的网站是一个有漏洞的网站,但是他没有意识到;

(b)在这个网站中通过一些手段放入一段可以执行的代码,吸引客户执行(通过鼠标

         点击等);

(c)客户点击后,代码执行,可以达到攻击目的。

  解决方案:对用户输入的数据进行HTML转移处理。如今很多开源框架默认就支持

                    HTML的转义。

2.CSRF攻击(Cross Site Request Forgery, 跨站域请求伪造)

  你这可以这么理解 CSRF 攻击:攻击者盗用了你的身份,伪装成你发送恶意请求。

  CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购

  买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。

  具体攻击过程如下:

(1)用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;

(2)在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登

         录网站A成功,可以正常发送请求到网站A;

(3)用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;

(4)网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第

         三方站点A

  解决方案:

(1)将cookie设置成HttpOnly

(2)增加token

         其原理是在请求中放入攻击者所不能伪造的信息,并且该新信息不存在于cookie

         中。鉴于此,系统开发人员可以在HTTP请求中以参数的形式加入一个随机产生

         的token,并在服务端进行token验证,如果请求中没有token或者token内容不正

         确,则认为CSRF攻击而拒绝该请求。例如,token可以存放在表单中的隐藏域

         中:<input type="hidden" name="_token" value="tokenvalue"/>。token的值通

         过服务端生成,表单提交后token的值通过POST请求与参数一同带到服务端,

         每次回话可以使用相同的token,会话过期,则token失效,攻击者因无法获取

         token,也就无法伪造请求。

         

HttpSession session=request.getSession()
Object token=session.getattribute("_token")
if(token==null||"".equals(token))
{
    session.setattribute("_token",UUID.randomUUID().toString());
}

3.SQL注入攻击

  解决方案:

(1)使用预编译语句(PreparedStatement)

         预编译语句使用参数占位符来替代需要动态传入的参数,这样攻击者无法改变

         SQL语句的结构,SQL语句的语义不会发生变化,即便用户输入sql,它会将其

         转义。

         例如,原语句:

         select * from hhuser where nick=nickname and password=password

         例如用户输入 'or '1'='1时,不使用预编译,生成语句为:

         select * from hhuser where nick='zhangsan' and password='' or '1'='1'

         使用预编译:        

         select * from hhuser where nick='zhangsan' and password='\' or \'1\'=\'1'

         可见发生了转义。

(2)使用ORM框架,如IBATIS和Hibernate等都支持输入变量的转义

         实现办法时通过#配置变量

4.文件上传漏洞

(1)一般处理方法

         为了防止用户上传恶意的可执行文件和脚本,以及将文件服务器当做免费的文

         件存储服务器使用,我们需要对上传的文件进行白名单校验并限制上传文件

         大小,上传文件需要重新命名,使共攻者无法猜测上传文件的访问路径。对于

         上传的文件来说,不能简单地通过后缀名称判断文件的类型,因为恶意攻击可

         以将可执行文件的后缀名称改成图片或者其它后缀类型,诱导用户执行。因

         此,判断文件类型需要使用更安全的方式,很多类型的文件起使得几个字节内

         容使固定得,根据这几个字节的内容,就可以确定文件的类型,这几个字节被

         称为魔数。

(2)配合使用imagemaglck

         对于图片类型的文件,可以上传后对图片进行相应的缩放,破坏恶意用户上传

         的二进制可执行文件的结构。imagemaglck是一套功能强大、稳定并且开源的

         对图片进行处理的开发工具包,能处理多种格式的图片文件,可以利用

         imagemaglck来对图片进行缩放。

         魔数枚举类型:

public enum FileType {

    /** JPEG */
    JPEG("FFD8FF"),

    /** PNG */
    PNG("89504E47"),

    /** GIF */
    GIF("47494638"),

    /** TIFF */
    TIFF("49492A00"),

    /** Windows bitmap */
    BMP("424D"),

    /** CAD */
    DWG("41433130"),

    /** Adobe photoshop */
    PSD("38425053"),

    /** Rich Text Format */
    RTF("7B5C727466"),

    /** XML */
    XML("3C3F786D6C"),

    /** HTML */
    HTML("68746D6C3E"),

    /** Outlook Express */
    DBX("CFAD12FEC5FD746F "),

    /** Outlook */
    PST("2142444E"),

    /** doc;xls;dot;ppt;xla;ppa;pps;pot;msi;sdw;db */
    OLE2("0xD0CF11E0A1B11AE1"),

    /** Microsoft Word/excel */
    XLS_DOC("D0CF11E0"),

    /** Microsoft Access */
    MDB("5374616E64617264204A"),

    /** Word Perfect */
    WPB("FF575043"),

    /** Postscript */
    EPS_PS("252150532D41646F6265"),

    /** Adobe Acrobat */
    pdf("255044462D312E"),

    /** Windows Password */
    PWL("E3828596"),

    /** ZIP Archive */
    ZIP("504B0304"),

    /** ARAR Archive */
    RAR("52617221"),

    /** WAVE */
    WAV("57415645"),

    /** AVI */
    AVI("41564920"),

    /** Real Audio */
    RAM("2E7261FD"),

    /** Real Media */
    RM("2E524D46"),

    /** Quicktime */
    MOV("6D6F6F76"),

    /** Windows Media */
    ASF("3026B2758E66CF11"),

    /** MIDI */
    MID("4D546864");

    private String value = "";

    private FileType(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

}

         

  

相关阅读

解决sql server2008数据库安装之后,web程序80端口被占

前言: 原来电脑上的Apache一直使用正常,在安装sql server2008后,突然发现Apache无法启动,检查了一下是因为80端口被强制占用了。 解

Web实战:如何进行视频截图

各位读者大人们好,不知道各位读者大人们近来如何。由于前段时间事情比较多,文章的更新就给耽误了,项目需要上线经常加班,再加上自己的

JavaWEB用户登录实现代码

1.环境搭建 环境那个建 2.了解MVC模型 model–view–controller 3.搭建登陆页面

百度图说——零编程玩转ECharts图表

百度图说 和 ECharts 都是百度ECharts团队研发的产品,在不懂编程或是为了快速完成图表制作的情况下,都可以通过百度图说这一工具实

JavaScript 滑动验证

因为在做一个门户网站,需要用到js滑动验证。原文https://blog.csdn.net/chy555chy/article/details/55294147html <p id="dragCo

分享到:

栏目导航

推荐阅读

热门阅读