一.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 blocke.printStackTrace();} catch (SQLException e) {e.printStackTrace();}}}@Overridepublic void run() {while (true) {try {this.zdfs();super.sleep(1000 * 60 * 10);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.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;}}

Java Web编程相关推荐

  1. Java Web 编程入门知识

    Java SE 的内容基本都讲完了. 但是 Java一般用于网络编程, 就是所谓的web编程. Java SE讲的基本上都是本地程序的内容. 而Java web编程需要在两个程序中传输数据, 以后就是 ...

  2. Java Web编程技术

    为什么80%的码农都做不了架构师?>>>    Java Web编程技术 该文档重点讲解如何自定义标签的开发,包括简单标签的开发.TLD文件.几种常见类型标签的开发. 对其内容详细阅 ...

  3. java web 编程技术 pdf_Java WEB编程技术.pdf

    您所在位置:网站首页 > 海量文档 &nbsp>&nbsp计算机&nbsp>&nbspJava Java WEB编程技术.pdf289页 本文档一共被 ...

  4. java web编程技术解题与实验指导_javaweb编程技术实验指导书

    javaweb编程技术实验指导书 <Java Web编程技术> 实 验 指 导 书 沈泽刚 编写2010 年 3 月目 录 实验一 简单的 Servlet 与 JSP .1 实验二 HTT ...

  5. java web编程技术上机实验_JavaWeb編程技术实验指导书.doc

    JavaWeb編程技术实验指导书 <Java Web编程技术> 实 验 指 导 书 沈泽刚 编写 2010年3月 目 录 实验一 简单的Servlet与JSP1 实验二 HTTP请求对象3 ...

  6. 用php web编程作业,代做CSE2ISD作业、代做Web,php程序作业、代写Java/web编程作业、代写C/C++/Java留学生作业...

    代做CSE2ISD作业.代做Web,php程序作业.代写Java/web编程作业.代写C/C++/Java留学生作业 日期:2018-10-08 10:00 CSE2ISD – Information ...

  7. Java Web编程的主要组件技术——MVC设计模式

    参考书籍:<J2EE开源编程精要15讲> MVC(Model View Controller),Model(模型)表示业务逻辑层,View(视图)代表表述层,Controller(控制)表 ...

  8. 学习(Java Web)编程技术要点及方向; 完成项目的要决

    本文亮点: 传统学习编程技术落后,应跟著潮流,要对业务聚焦处理. 要Jar, 不要War:以小为主,以简为宝,集堆而成. 去繁取简 Spring Boot,明日之春. 集堆综合技术如 jHipster ...

  9. 合肥工业大学宣城校区Java技术实验四 Java Web编程

    (本实验只完成了一部分,属于半成品) 一.实验目的 1.掌握Java Web服务器Tomcat的安装.配置. 2.学会简单的HTML表单设计,表单提交. 3.掌握JSP中的request对象.sess ...

最新文章

  1. 用哪种语言写的应用漏洞最严重?六大主流语言代码漏洞分析报告出炉
  2. SAP PM 初级系列20 - 维修工单的检验批
  3. 关于maven依赖中的scopeprovided/scope使用
  4. overleaf表格_latex 表格制作
  5. 我们身边的知识产权单元测试答案(期末考试复习)【湘潭大学】
  6. Apache POI组件操作Excel,制作报表(四)
  7. c语言发牌小游戏,大家想想怎么用c实现我们经常玩的斗地主游戏的发牌过程呢?...
  8. 计算机应用助手工程师,通信工程师备考助手
  9. 国际版云购网站代码开发实现案例
  10. java火柴人吃豆豆,4399游戏火柴人吃豆豆全图文通关攻略分享
  11. 鲲志说:向我跌宕起伏,喜忧参半的2022致敬!
  12. 【读书随记】周末充电,学习Java更轻松(文末送书)
  13. java实现支付宝扫码支付详细步骤
  14. 移动互联网下一章(转载)
  15. EasyCVR实时录像接口教程:如何获取国标接入的摄像头设备录像?
  16. python资源论坛_五个亲测可用的Python论坛类网站开源框架
  17. 开通知乎专栏和公众号啦!
  18. 有关Scrollview嵌套ListView的那些事
  19. 微信 图片二维码识别不了的问题
  20. IDEA上的项目文件不慎删除了该怎么办

热门文章

  1. 双网卡同网段静态路由_WINDOWS系统下双网卡设置路由 本文主要涉及到静态路由...
  2. HDFS名字空间(NameSpace)
  3. 钱钟书是怎样做读书笔记的 杨绛
  4. 让curl支持IE代理
  5. vue-iview异步加载渲染树
  6. 数字体验词汇表:您需要了解的最重要术语
  7. Linux Panic 机制解析
  8. 编解码base64、对称加密aes和非对称加密rsa
  9. 【低功耗蓝牙】② 蓝牙状态切换和事件处理
  10. 可供软件测试练习的在线网站、被测系统——整理中