海王金樽保质期,都市一时间,张铁桥
在java web程序中,servlet主要负责接收用户请求 httpservletrequest
,在doget()
,dopost()
中做相应的处理,并将回应httpservletresponse
反馈给用户。servlet 可以设置初始化参数,供servlet内部使用。一个servlet类只会有一个实例,在它初始化时调用init()
方法,销毁时调用destroy()
方法。servlet需要在web.xml中配置,一个servlet可以设置多个url访问。servlet不是线程安全的,因此要谨慎使用成员变量。
servlet接口定义了5个方法,其中前三个方法与servlet生命周期相关:
void init(servletconfig config) throws servletexception
void service(servletrequest req, servletresponse resp) throws servletexception, java.io.ioexception
void destroy()
生命周期: web容器加载servlet并将其实例化后,servlet生命周期开始,容器运行其init()方法进行servlet的初始化;请求到达时调用servlet的service()方法,service()方法会根据需要调用与请求对应的doget或dopost等方法;当服务器关闭或项目被卸载时服务器会将servlet实例销毁,此时会调用servlet的destroy()方法。init方法和destroy方法只会执行一次,service方法客户端每次请求servlet都会执行。servlet中有时会用到一些需要初始化与销毁的资源,因此可以把初始化资源的代码放入init方法中,销毁资源的代码放入destroy方法中,这样就不需要每次处理客户端的请求都要初始化与销毁资源。
get和post底层都是http,使用的都是tcp协议。
get在浏览器回退时是无害的,而post会再次提交请求。
get产生的url地址可以被bookmark,而post不可以。
get请求会被浏览器主动cache,而post不会,除非手动设置。
get请求只能进行url编码,而post支持多种编码方式。
get请求参数会被完整保留在浏览器历史记录里,而post中的参数不会被保留。
get请求在url中传送的参数是有长度限制的,而post没有。
对参数的数据类型,get只接受ascii字符,而post没有限制。
get比post更不安全,因为参数直接暴露在url上,所以不能用来传递敏感信息。
get参数通过url传递,post放在request body中。
get和post还有一个重大区别:get产生一个tcp数据包;post产生两个tcp数据包。
对于get方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
对于post,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的tcp在验证数据包完整性上,有非常大的优点。
并不是所有浏览器都会在post中发送两次包,firefox就只发送一次。
form标签里的method的属性为get时调用doget(),为post时调用dopost()。
处理get请求时调用doget,处理post请求时调用dopost()
转发是服务器内部转发,重定向是服务器通知客户端请求一个新的地址
转发(forward) 通过requestdispatcher对象的forward(httpservletrequest request,httpservletresponse response)方法实现的。requestdispatcher对象可以通过httpservletrequest 的getrequestdispatcher()方法获得。
eg.登录成功,转发到login_success.jsp页面:
request.getrequestdispatcher("login_success.jsp").forward(request, response);
重定向(redirect) 是利用服务器返回的状态码来实现的。客户端浏览器请求服务器的时候,服务器会返回一个状态码。服务器通过 httpservletresponse
的 setstatus(int status)
方法设置状态码。如果服务器返回301或者302,则浏览器会到新的网址重新请求该资源。
forward:地址栏的url还是原来的那个,不变;redirect:地址栏的url会变为重定向的url
forward:转发到的页面可以共享request里面的数据. redirect:不能共享数据.
forward:一般用于用户登陆的时候,登录成功时根据角色转发到相应的模块. redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等
forward:高,因为是1次http请求,服务器本地转发到本地,速度快;redirect:低,因为是2次http请求,在客户端、服务器之间来回跑花时间。
自动刷新不仅可以实现一段时间后自动跳转到另一个页面,还可以实现一段时间后自动刷新本页面。servlet中通过httpservletresponse对象设置header属性实现自动刷新例如:
response.setheader("refresh","5;url=http://localhost:8080/servlet/example.html");
其中5为时间,单位为秒。url指定就是要跳转的页面,如果设置为本页面,每隔5s就会自动刷新本页面。因为5秒之后再次请求本页面,本页面的响应头依然是5秒后刷新,一直循环往复。
servlet不是线程安全的,因为运行时一个servlet只有一个实例,多个客户端同时访问这个servelt的映射地址,tomcat会为每一个请求都创建一个线程来处理,这些线程同时调用同一个servlet实例来处理请求(访问同一个servlet的成员变量),多线程并发的读写会导致数据不同步的问题,如果并发访问都是只读servlet中的变量、不写入(修改),那倒是没有问题。尽量把只读的变量设置为final。
可以给成员变量加同步锁,但执行效率很低,会有大批请求等待。
解决的办法是servlet中尽量不要定义成员变量,使用的变量尽量放到成员方法doget、dopost中作为局部变量。
servlet是一个特殊的java程序,它运行于服务器的jvm中,能够依靠服务器的支持向浏览器提供显示内容。
jsp本质上是servlet,运行时jsp会先被服务器转换为servlet。
servlet和jsp最主要的不同点在于,servlet的应用逻辑是在.java文件中,完全同表现层的html分开;而jsp是java和html杂糅在一起组合.jsp文件。
jsp侧重于视图,servlet更侧重于逻辑控制,在mvc架构模式中,jsp适合充当视图(view)而servlet适合充当控制器(controller)。
jsp是一种servlet,但是与servlet的工作方式不太一样。servlet是先由源代码编译为class文件后部署到服务器下,先编译后部署。而jsp则是先部署后编译。tomcat会在客户端第一次请求jsp文件时把.jsp转换为.java文件(servlet),使用的是httpjsppage类(servlet接口的一个子类),再编译为.class文件。.java、.class这2个文件会被临时存放在服务器工作目录里。编译完毕后再运行class文件来响应客户端请求。以后客户端访问login.jsp的时候,tomcat将不再重新编译jsp文件,而是直接调用class文件来响应客户端请求。第一次访问jsp要转换、编译,速度慢,后续访问此jsp就快了。
jsp有9个内置对象:
1、page指令 设置jsp页面的相关信息
实例:<%@ page language=”java” import=”java.util.*” pageencoding=”utf-8”%>
在一个jsp页面中可以给出多个page指令,而且import是可以重复出现的
如果pageencoding没有指定,那么默认为contenttype的值;
如果pageencoding和contenttype都没有指定,那么默认值为iso-8859-1
如果没有指定contenttype属性,那么默认为pageencoding的值;
如果contenttype和pageencoding都没有指定,那么默认值为iso-8859-1
例如:<%@ page errorpage=”b.jsp” %>
buffer:指定out流的缓冲区大小,默认为8kb
autoflush:当autoflush为true时,表示out流缓冲区满时会自动刷新。默认为true
language:当前jsp使用的语言,默认为java,也只能选择java
info:当前jsp的说明信息
isthreadsafe:当前jsp是否是线程安全的(是否只支持单线程访问),默认为false,表示支持并发访问
2、include指令 包含其他文件
被包含的文件可以是jsp文件、html文件或文本文件。包含的文件就好像是该jsp文件的一部分,会被同时编译执行。
实例:<%@ include file=”文件相对 url 地址” %>
3、taglib指令 在当前jsp页面中导入第三方的标签库
实例:<%@ taglib uri=”http://java.sun.com/jsp/jstl/core” % prefix=”c” >
需要先添加第三方标签库所需的jar包。
jsp:include:引入一个文件。
jsp:usebean:寻找或者实例化一个 javabean。
jsp:setproperty:设置 javabean 的属性。
jsp:getproperty:输出某个 javabean 的属性。
jsp:forward:把请求转到一个新的页面。
jsp:plugin:根据浏览器类型为 java 插件生成 object 或 embed 标记
1、获取的数据:getparameter()
是获取 post/get 传递的参数值(比如表单提交的数据);getattribute()
是获取setattribute()放到域中的数据。
2、返回值:getparameter()
返回的是string,需要转换为自己需要的相应类型;getattribute()
返回的是object,也需要转换为自己需要的相应类型
3、使用场景:request.getparameter()常用于直接获取http请求中携带的请求参数,比如获取表单表单提交的数据,request.getattribute()常用于转发时获取前一个页面setattribute传递的数据。
include指令: jsp可以通过include指令来包含其他文件。被包含的文件可以是jsp文件、html文件或文本文件。包含的文件就好像是该jsp文件的一部分,会被同时编译执行。 语法格式如下: <%@ include file="文件相对 url 地址" %>
include动作元素: <jsp:include>
动作元素用来包含静态和动态的文件。该动作把指定文件插入正在生成的页面。语法格式如下: <jsp:include page="相对 url 地址" flush="true" />
servlet默认是单实例、支持多线程访问的(并发访问),jsp本质是servlet,也一样。
设置为单线程访问:jsp可以通过page指令进行设置, <%@page isthreadsafe="false"%>;
servlet可以让servlet实现singlethreadmodel标识接口。
说明:如果将jsp或servlet设置成单线程工作模式,会导致每个请求创建一个servlet实例,这种实践将导致严重的性能问题(服务器的内存压力很大,还会导致频繁的垃圾回收),所以通常情况下并不会这么做。
1、使用cookie
优点: 数据可以持久保存,不占用服务器存储,基于文本的key-value,使用简单
缺点: 大小受到限制(每次请求该网站时都会将该网站的cookie放在请求头中),用户可以禁用cookie功能,由于保存在客户端,有一定的安全风险。
2、session
在所有会话跟踪技术中,session对象是最强大也是功能最多的。当一个用户第一次访问某个网站时会自动创建 httpsession,每个用户可以访问他自己的httpsession。可以通过httpservletrequest对象的getsession方 法获得httpsession,通过httpsession的setattribute方法可以将一个值放在httpsession中,通过调用 httpsession对象的getattribute方法,同时传入属性名就可以获取保存在httpsession中的对象。与上面三种方式不同的 是,httpsession放在服务器的内存中,因此不要将过大的对象放在里面,即使目前的servlet容器可以在内存将满时将httpsession 中的对象移到其他存储设备中,但是这样势必影响性能。添加到httpsession中的值可以是任意java对象,这个对象最好实现了 serializable接口,这样servlet容器在必要的时候可以将其序列化到文件中,否则在序列化时就会出现异常。
3、url 重写
在url中添加用户会话的信息作为请求的参数,或者将唯一的会话id添加到url结尾以标识一个会话。
优点: 在cookie被禁用的时候依然可以使用
缺点: 必须对网站的url进行编码,所有页面必须动态生成,不能用预置的url进行访问。
4、隐藏的表单域
<input type="hidden" name ="session" value="..."/>
优点: cookie被禁时可以使用
缺点:需要提交表单才能向服务器传递数据,且只能是单向传递(客户端=>服务器)
cookie 和 session都是用来跟踪用户会话的,区别:
1、存储位置:cookie 数据保存在客户端(浏览器端),session 数据保存在服务器端。
2、安全性:session存储在服务器上,相对来说安全性更高。 尽量不要把敏感信息存储在 cookie 中,就算要在cookie中存储敏感信息,也应该存储加密后的信息。服务器拿到加密后的信息后先解密再使用。
3、跟踪用户会话的实现方式
cookie:服务器把cookie(会话信息)存储在客户端(浏览器),每次向该网站发送http请求时,都会在请求头中附带该网站的cookie,请求头的大小有限,所以cookie能存储信息大小是有限的。
session:session(会话信息)存储在服务器上,使用一个唯一的sessionid来唯一标识此session对象,sessionid以cookie的方式保存在客户端,客户端发起http请求时,服务器会自动从cookie中获取sessionid,找到对应的session对象。
4、用户信息的保存时间
cookie:在cookie有效期内,cookie中的用户信息都有效,可以长期保存用户信息。
session:只是在本次会话期间保存会话信息,session超时时会自动删除服务器上的对应的session对象,默认超时时间是30min,即用户30min内没有再次访问服务器,session对象就会被删除。
有时候需要在删除session对象时做一些处理,比如把session中的一些数据以后还要用,需要保存至数据库。那就需要我们写一个监听器来监听session,session销毁时做一些处理:
@weblistener() public class mylistener implements httpsessionlistener { public void sessioncreated(httpsessionevent se) { } public void sessiondestroyed(httpsessionevent se) { httpsession session = se.getsession(); //从session中获取数据,存储到数据库中 //...... } }
5、使用场景
cookie 一般用来保存用户信息 ,比如:
(1)在 cookie 中保存已经登录过的用户信息,下次访问网站的时候自动登录或自动填写一些字段;
(2)一般的网站都会保持登录,就是说下次你再访问网站的时候不需要重新登录,这是因为用户登录时存放了一个 token 在 cookie 中,下次登录的时候只需要根据 token 值来查找用户即可(为了安全考虑,重新登录一般要将 token 重写);
session存储的信息大小没有限制,可存储本次会话期间的信息,基于这2个特点,常见的应用有
(1)session常用来存储一次性验证码,将用户提交的验证码与session中正确的验证码比较,验证码30分钟内有效是设置sessionid这个cookie的有效期是30min。
(2)购物车
原文出处:
https://snailclimb.gitee.io/javaguide/#/docs/java/j2ee%e5%9f%ba%e7%a1%80%e7%9f%a5%e8%af%86
在原文基础上进行了部分修改
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
apollo与springboot集成实现动态刷新配置的教程详解
网友评论