- 1、Servlet 总结
- 2、Servlet 的优点
- 3、Servlet 接口中有哪些方法
- Servlet 生命周期
- get 和 post 请求的区别
- 什么情况下调用 doGet() 和 doPost()
- 转发(Forward)和重定向(Redirect)的区别
- 自动刷新(Refresh)
- Servlet与线程安全
- JSP 和 Servlet 是什么关系
- JSP工作原理
- JSP有哪些内置对象、作用分别是什么
- Request对象的主要方法有哪些
- request.getAttribute() 和 request.getParameter() 有何区别
- include 指令 include 行为的区别
- JSP九大内置对象,七大动作,三大指令
- 讲解JSP中的四种作用域
- 如何实现 JSP 或 Servlet 的单线程模式
- 实现会话跟踪的技术有哪些
- Cookie和Session的的区别
1、Servlet 总结
- Servlet 是一个特殊的 Java 程序,一个基于 Java 的 Web 应用通常包含一个或多个 Servlet 类。
- Servlet 不能自行创建并执行,它是在 Servlet 容器中运行的,容器将用户的请求传递给 Servlet 程序,并将 Servlet 的响应回传给用户。
- 通常一个 Servlet 会关联一个或多个 JSP 页面。
- 在 Java Web 程序中,Servlet 主要负责接收用户请求
HttpServletRequest
,在doGet()
,doPost()
中做相应的处理,并将回应HttpServletResponse
反馈给用户。 - Servlet 可以设置初始化参数,供 Servlet 内部使用。
- 一个 Servlet 类只会有一个实例,在它初始化时调用
init()
方法,销毁时调用destroy()
方法。 - Servlet 需要在
web.xml
中配置,一个 Servlet 可以设置多个 URL 访问。 - Servlet 是非线程安全的,因此要谨慎使用类变量。
2、Servlet 的优点
- 只需要启动一个操作系统进程以及加载一个JVM,大大降低了系统的开销
- 如果多个请求需要做同样处理的时候,这时候只需要加载一个类,这也大大降低了开销
- 所有动态加载的类可以实现对网络协议以及请求解码的共享,大大降低了工作量。
- Servlet 能直接和 Web 服务器交互,Servlet 还能在各个程序之间共享数据,使数据库连接池之类的功能很容易实现。
3、Servlet 接口中有哪些方法
Servlet 接口定义了5个方法,其中前三个方法与 Servlet 生命周期相关:
void init(ServletConfig config) throws ServletException
void service(ServletRequest req, ServletResponse resp) throws ServletException, java.io.IOException
void destroy()
String getServletInfo()
ServletConfig getServletConfig()
Servlet 生命周期
- Web 容器加载 Servlet 并将其实例化后,Servlet 生命周期开始
- 容器运行其
init()
方法进行 Servlet 的初始化; - 请求到达时调用 Servlet 的
service()
方法,service()
方法会根据需要调用与请求对应的doGet()
或doPost()
等方法; - 当服务器关闭或项目被卸载时服务器会将 Servlet 实例销毁,此时会调用 Servlet 的
destroy()
方法。
init()
方法和destroy()
方法只会执行一次,service()
方法客户端每次请求 Servlet 都会执行。
Servlet 中有时会用到一些需要初始化与销毁的资源,因此可以把初始化资源的代码放入init()
方法中,销毁资源的代码放入destroy()
方法中,这样就不需要每次处理客户端的请求都要初始化与销毁资源。
get 和 post 请求的区别
可以把 get 和 post 当作两个不同的行为,两者并没有什么本质区别,底层都是 TCP 连接。 get 请求用来从服务器上获得资源,而 post 是用来向服务器提交数据。比如你要获取人员列表可以用 get 请求,你需要创建一个人员可以用 post 。这也是 Restful API 最基本的一个要求。
什么情况下调用 doGet() 和 doPost()
Form 标签里的 method 属性为 get 时调用 doGet()
,为 post 时调用 doPost()
。
转发(Forward)和重定向(Redirect)的区别
转发是服务器行为,重定向是客户端行为。
转发(Forward) 是通过 RequestDispatcher
的 forward(HttpServletRequest request,HttpServletResponse response)
方法实现的。
重定向(Redirect) 是利用服务器返回的状态码来实现的。客户端浏览器请求服务器的时候,服务器会返回一个状态码。服务器通过 HttpServletResponse
的 setStatus(int status)
方法设置状态码。如果服务器返回 301 或者 302,则浏览器会到新的网址重新请求该资源。
从地址栏显示来说
- forward 是服务器请求资源,服务器直接访问目标地址的 URL,把那个 URL 的响应内容读取过来,然后把这些内容再发给浏览器。浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址。
- redirect 是服务端根据逻辑发送的一个状态码,告诉浏览器重新去请求那个地址。所以地址栏显示的是新的 URL。
从数据共享来说
- forward:转发页面和转发到的页面可以共享request里面的数据。
- redirect:不能共享数据
从运用地方来说
- forward:一般用于用户登陆的时候,根据角色转发到相应的模块
- redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等
从效率来说
- forward: 高
- redirect: 低
自动刷新(Refresh)
自动刷新不仅可以实现一段时间之后自动跳转到另一个页面,还可以实现一段时间之后自动刷新本页面。Servlet中通过 HttpServletResponse
对象设置 Header 属性实现自动刷新
例如
Response.setHeader("Refresh","5;URL=http://localhost:8080/servlet/example.htm");
其中 5 为时间,单位为秒。URL 指定就是要跳转的页面(如果设置自己的路径,就会实现每过5秒自动刷新本页面一次)
Servlet与线程安全
Servlet不是线程安全的,多线程并发的读写会导致数据不同步的问题。
解决的办法是尽量不要定义 name 属性,而是要把 name 变量分别定义在 doGet()
和 doPost()
方法内。虽然使用 synchronized(name){}
语句块可以解决问题,但是会造成线程的等待,不是很科学的办法。
注意:多线程的并发的读写 Servlet 类属性会导致数据不同步。但是如果只是并发地读取属性而不写入,则不存在数据不同步的问题。
因此 Servlet 里的只读属性最好定义为 final 类型的。
JSP 和 Servlet 是什么关系
Servlet 是一个特殊的 Java 程序,它运行于服务器的 JVM 中,能够依靠服务器的支持向浏览器提供显示内容。
JSP 本质上是 Servlet 的一种简易形式,JSP 会被服务器处理成一个类似于 Servlet 的 Java 程序,可以简化页面内容的生成。Servlet 和JSP最主要的不同点在于:
Servlet 的应用逻辑是在 Java 文件中,并且完全从表示层中的 HTML 分离开来。
而 JSP 的情况是 Java 和 HTML 可以组合成一个扩展名为 .jsp 的文件。
有人说,Servlet就是在 Java 中写HTML,而 JSP 就是在 HTML 中写 Java 代码,当然这个说法是很片面且不够准确的。JSP侧重于视图,Servlet 更侧重于控制逻辑,在 MVC 架构模式中,JSP 适合充当视图(view)而 Servlet 适合充当控制器(controller)。
JSP工作原理
JSP 是一种 Servlet,但是与 HttpServlet 的工作方式不太一样。
HttpServlet 是先由源代码编译为 class 文件后部署到服务器下,为先编译后部署。而JSP则是先部署后编译。
JSP 会在客户端第一次请求 JSP 文件时被编译为 HttpJspPage类(接口Servlet的一个子类)。
该类会被服务器临时存放在服务器工作目录里面。下面通过实例给大家介绍。 工程 JspLoginDemo 下有一个名为 login.jsp
的 JSP 文件,把工程第一次部署到服务器上后访问这个 JSP 文件,我们发现这个目录下多了下图这两个东西。 .class
文件便是 JSP 对应的 Servlet。编译完毕后再运行 class 文件来响应客户端请求。以后客户端访问 login.jsp
的时候,Tomcat 将不再重新编译 JSP 文件,而是直接调用 class 文件来响应客户端请求。 由于JSP只会在客户客户端第一次请求的时候会被编译 ,因此第一次请求 JSP 时会感觉比较慢,之后就会感觉快很多。如果把服务器保存的 class 文件删除,服务器会重新编译 JSP。
开发 Web 程序时经常需要修改 JSP。Tomcat 能够自动检测到 JSP 程序的改动。如果检测到 JSP 源代码发生了改动。Tomcat 会在下次客户端请求 JSP 时重新编译 JSP,而不需要重启 Tomcat。这种自动检测功能是默认开启的,检测改动会消耗少量的时间,在部署Web应用的时候可以在 web.xml
中将它关掉。
JSP有哪些内置对象、作用分别是什么
JSP有9个内置对象:
- request:封装客户端的请求,其中包含来自GET或POST请求的参数;
- response:封装服务器对客户端的响应;
- pageContext:通过该对象可以获取其他对象;
- session:封装用户会话的对象;
- application:封装服务器运行环境的对象;
- out:输出服务器响应的输出流对象;
- config:Web 应用的配置对象;
- page:JSP 页面本身(相当于Java 程序中的 this);
- exception:封装页面抛出异常的对象。
Request对象的主要方法有哪些
setAttribute(String name,Object)
:设置名字为name的request 的参数值getAttribute(String name)
:返回由name指定的属性值getAttributeNames()
:返回request 对象所有属性的名字集合,结果是一个枚举的实例getCookies()
:返回客户端的所有 Cookie 对象,结果是一个Cookie 数组getCharacterEncoding()
:返回请求中的字符编码方式 = getContentLength() :返回请求的 Body的长度getHeader(String name)
:获得HTTP协议定义的文件头信息getHeaders(String name)
:返回指定名字的request Header 的所有值,结果是一个枚举的实例getHeaderNames()
:返回所以request Header 的名字,结果是一个枚举的实例getInputStream()
:返回请求的输入流,用于获得请求中的数据getMethod()
:获得客户端向服务器端传送数据的方法getParameter(String name)
:获得客户端传送给服务器端的有 name指定的参数值getParameterNames()
:获得客户端传送给服务器端的所有参数的名字,结果是一个枚举的实例getParameterValues(String name)
:获得有name指定的参数的所有值getProtocol()
:获取客户端向服务器端传送数据所依据的协议名称getQueryString()
:获得查询字符串getRequestURI()
:获取发出请求字符串的客户端地址getRemoteAddr()
:获取客户端的 IP 地址getRemoteHost()
:获取客户端的名字getSession([Boolean create])
:返回和请求相关 SessiongetServerName()
:获取服务器的名字getServletPath()
:获取客户端所请求的脚本文件的路径getServerPort()
:获取服务器的端口号removeAttribute(String name)
:删除请求中的一个属性
request.getAttribute() 和 request.getParameter() 有何区别
从获取方向来看:
getParameter()
是获取 GET/POST 传递的参数值;
getAttribute()
是获取对象容器中的数据值;
从用途来看:
getParameter()
用于客户端重定向时,点击了链接或提交按扭时传值用,即用于在用表单或 url 重定向传值时接收数据用。
getAttribute()
用于服务器端重定向时,在 servlet 中使用 forward 函数,或 struts 中使用了 mapping.findForward
。 getAttribute()
只能收到程序用 setAttribute()
传过来的值。
另外,可以用 setAttribute()
,getAttribute()
发送接收对象.而 getParameter()
显然只能传字符串。
setAttribute()
是应用服务器把这个对象放在该页面所对应的一块内存中,当你的页面服务器重定向到另一个页面时,应用服务器会把这块内存拷贝到另一个页面所对应的内存中。这样getAttribute()
就能取得你所设下的值,当然这种方法可以传对象。session 也一样,只是对象在内存中的生命周期不一样而已。getParameter()
只是应用服务器在分析你送上来的 request 页面的文本时,取得你设在表单或 url 重定向时的值。
总结:
getParameter()
返回的是String,用于读取提交的表单中的值;(获取之后会根据实际需要转换为自己需要的相应类型,比如整型,日期类型等等)
getAttribute()
返回的是Object,需进行转换,可用setAttribute()
设置成任意对象,使用很灵活,可随时用
include 指令 include 行为的区别
include指令:
- JSP 可以通过 include 指令来包含其他文件。被包含的文件可以是 JSP 文件、HTML 文件或文本文件。包含的文件就好像是该 JSP 文件的一部分,会被同时编译执行。 语法格式如下:
<%@ include file="文件相对 url 地址" %>
include动作:
<jsp:include>
动作元素用来包含静态和动态的文件。该动作把指定文件插入正在生成的页面。语法格式如下:<jsp:include page="相对 URL 地址" flush="true" />
JSP九大内置对象,七大动作,三大指令
讲解JSP中的四种作用域
JSP中的四种作用域包括 page、request、session、application,具体来说:
- page 代表与一个页面相关的对象和属性。
- request 代表与 Web 客户端发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件;需要在页面显示的临时数据可以置于此作用域。
- session 代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的 session 中。
- application 代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局作用域。
如何实现 JSP 或 Servlet 的单线程模式
对于 JSP 页面,可以通过page指令进行设置。 <%@page isThreadSafe="false"%>
对于 Servlet,可以让自定义的 Servlet 实现 SingleThreadModel
标识接口。
说明:如果将 JSP 或 Servlet 设置成单线程工作模式,会导致每个请求创建一个 Servlet 实例,这种实践将导致严重的性能问题(服务器的内存压力很大,还会导致频繁的垃圾回收),所以通常情况下并不会这么做。
实现会话跟踪的技术有哪些
使用 Cookie
- Cookie 是服务器通知客户端保存键值对的一种技术
- 优点: 数据可以持久保存,不需要服务器资源,客户端有了Cookie后,每次请求都会发送给服务器,简单,基于文本的Key-Value,
- 缺点: 大小受到限制,不能超过 4 kb,用户可以禁用Cookie功能,由于保存在本地,有一定的安全风险。
URL 重写
- 在 URL 中添加用户会话的信息作为请求的参数,或者将唯一的会话ID添加到URL结尾以标识一个会话。
- 优点: 在 Cookie 被禁用的时候依然可以使用
- 缺点: 必须对网站的URL进行编码,所有页面必须动态生成,不能用预先记录下来的 URL 进行访问。
隐藏的表单
<intput type = "hidden">
- 优点: Cookie被禁时可以使用
- 缺点: 所有页面必须是表单提交之后的结果。
HttpSession
- 在所有会话跟踪技术中,HttpSession 对象是最强大也是功能最多的。当一个用户第一次访问某个网站时会自动创建 HttpSession,每个用户可以访问他自己的 HttpSession。可以通过 HttpServletRequest 对象的
getSession()
方法获得HttpSession,通过 HttpSession 的setAttribute()
方法可以将一个值放在 HttpSession 中,通过调用 HttpSession 对象的getAttribute()
方法,同时传入属性名就可以获取保存在 HttpSession 中的对象。 - 与上面三种方式不同的是,HttpSession 放在服务器的内存中,因此不要将过大的对象放在里面,即使目前的 Servlet 容器可以在内存将满时将 HttpSession 中的对象移到其他存储设备中,但是这样势必影响性能。添加到 HttpSession 中的值可以是任意 Java对象,这个对象最好实现了
Serializable
接口,这样 Servlet 容器在必要的时候可以将其序列化到文件中,否则在序列化时就会出现异常。
- 在所有会话跟踪技术中,HttpSession 对象是最强大也是功能最多的。当一个用户第一次访问某个网站时会自动创建 HttpSession,每个用户可以访问他自己的 HttpSession。可以通过 HttpServletRequest 对象的
Cookie和Session的的区别
Cookie 和 Session都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。
Cookie 一般用来保存用户信息
- 我们在 Cookie 中保存已经登录过得用户信息,下次访问网站的时候页面可以自动帮你登录的一些基本信息给填了;
- 一般的网站都会有保持登录也就是说下次你再访问网站的时候就不需要重新登录了,这是因为用户登录的时候我们存放了一个 Token 在 Cookie 中,下次登录的时候只需要根据 Token 值来查找用户即可(为了安全考虑,重新登录一般要将 Token 重写);
Session 主要是通过服务端记录用户的状态
- 登录一次网站后访问网站其他页面不需要重新登录。典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了。
Cookie 数据保存在浏览器端,Session 数据保存在 服务端,相对来说 Session 安全性更高。一些敏感信息不要写入 Cookie 中,最好能将 Cookie 信息加密然后使用的时候再去服务端解密。