系列文章请查看:
超详细的 Java 面试题总结 (一) 之 Java 基础知识篇
超详细的 Java 面试题总结 (二) 之 Java 基础知识篇
超详细的 Java 面试题总结 (三) 之 Java 集合篇常见问题
下面的都是自己之前在学习 Javaweb 的时候总结的, 对于巩固 JavaWeb 的基础知识应该有很大帮助后面还会把框架的面试题总结一下
Servlet 总结:
在 Java Web 程序中, Servlet 主要负责接收用户请求 HttpServletRequest, 在 doGet(),doPost()中做相应的处理, 并将回应 HttpServletResponse 反馈给用户 Servlet 可以设置初始化参数, 供 Servlet 内部使用一个 Servlet 类只会有一个实例, 在它初始化时调用 init()方法, 销毁时调用 destroy()方法 Servlet 需要在 web.xml 中配置(MyEclipse 中创建 Servlet 会自动配置), 一个 Servlet 可以设置多个 URL 访问 Servlet 不是线程安全, 因此要谨慎使用类变量
阐述 Servlet 和 CGI 的区别?
CGI 的不足之处:
1, 需要为每个请求启动一个操作 CGI 程序的系统进程如果请求频繁, 这将会带来很大的开销
2, 需要为每个请求加载和运行一个 CGI 程序, 这将带来很大的开销
3, 需要重复编写处理网络协议的代码以及编码, 这些工作都是非常耗时的
Servlet 的优点:
1, 只需要启动一个操作系统进程以及加载一个 JVM, 大大降低了系统的开销
2, 如果多个请求需要做同样处理的时候, 这时候只需要加载一个类, 这也大大降低了开销
3, 所有动态加载的类可以实现对网络协议以及请求解码的共享, 大大降低了工作量
4,Servlet 能直接和 Web 服务器交互, 而普通的 CGI 程序不能 Servlet 还能在各个程序之间共享数据, 使数据库连接池之类的功能很容易实现
补充: Sun Microsystems 公司在 1996 年发布 Servlet 技术就是为了和 CGI 进行竞争, Servlet 是一个特殊的 Java 程序, 一个基于 Java 的 Web 应用通常包含一个或多个 Servlet 类 Servlet 不能够自行创建并执行, 它是在 Servlet 容器中运行的, 容器将用户的请求传递给 Servlet 程序, 并将 Servlet 的响应回传给用户通常一个 Servlet 会关联一个或多个 JSP 页面以前 CGI 经常因为性能开销上的问题被诟病, 然而 Fast CGI 早就已经解决了 CGI 效率上的问题, 所以面试的时候大可不必信口开河的诟病 CGI, 事实上有很多你熟悉的网站都使用了 CGI 技术
参考: javaweb 整合开发王者归来 P7
Servlet 接口中有哪些方法及 Servlet 生命周期探秘
Servlet 接口定义了 5 个方法, 其中前三个方法与 Servlet 生命周期相关:
- void init(ServletConfig config) throws ServletException
- void service(ServletRequest req, ServletResponse resp) throws ServletException, java.io.IOException
- void destory()
- java.lang.String getServletInfo()
- ServletConfig getServletConfig()
生命周期: Web 容器加载 Servlet 并将其实例化后, Servlet 生命周期开始, 容器运行其 init()方法进行 Servlet 的初始化; 请求到达时调用 Servlet 的 service()方法, service()方法会根据需要调用与请求对应的 doGet 或 doPost 等方法; 当服务器关闭或项目被卸载时服务器会将 Servlet 实例销毁, 此时会调用 Servlet 的 destroy()方法 init 方法和 destory 方法只会执行一次, service 方法客户端每次请求 Servlet 都会执行 Servlet 中有时会用到一些需要初始化与销毁的资源, 因此可以把初始化资源的代码放入 init 方法中, 销毁资源的代码放入 destroy 方法中, 这样就不需要每次处理客户端的请求都要初始化与销毁资源
参考: javaweb 整合开发王者归来 P81
get 和 post 请求的区别?
get 请求用来从服务器上获得资源, 而 post 是用来向服务器提交数据;
get 将表单中数据按照 name=value 的形式, 添加到 action 所指向的 URL 后面, 并且两者使用 "?" 连接, 而各个变量之间使用 "&" 连接; post 是将表单中的数据放在 HTTP 协议的请求头或消息体中, 传递到 action 所指向 URL;
get 传输的数据要受到 URL 长度限制(1024 字节即 256 个字符); 而 post 可以传输大量的数据, 上传文件通常要使用 post 方式;
使用 get 时参数会显示在地址栏上, 如果这些数据不是敏感数据, 那么可以使用 get; 对于敏感数据还是应用使用 post;
get 使用 MIME 类型 application/x-www-form-urlencoded 的 URL 编码 (也叫百分号编码) 文本的格式传递参数, 保证被传送的参数由遵循规范的文本组成, 例如一个空格的编码是 " "
补充: GET 方式提交表单的典型应用是搜索引擎 GET 方式就是被设计为查询用的
什么情况下调用 doGet()和 doPost()?
Form 标签里的 method 的属性为 get 时调用 doGet(), 为 post 时调用 doPost()
转发 (Forward) 和重定向 (Redirect) 的区别?
转发是服务器行为, 重定向是客户端行为
转发 (Forword) 通过 RequestDispatcher 对象的 forward(HttpServletRequest request,HttpServletResponse response) 方法实现的 RequestDispatcher 可以通过 HttpServletRequest 的 getRequestDispatcher()方法获得例如下面的代码就是跳转到 login_success.jsp 页面
request.getRequestDispatcher("login_success.jsp").forward(request, response);
重定向 (Redirect) 是利用服务器返回的状态吗来实现的客户端浏览器请求服务器的时候, 服务器会返回一个状态码服务器通过 HttpServletRequestResponse 的 setStatus(int status) 方法设置状态码如果服务器返回 301 或者 302, 则浏览器会到新的网址重新请求该资源
从地址栏显示来说
forward 是服务器请求资源, 服务器直接访问目标地址的 URL, 把那个 URL 的响应内容读取过来, 然后把这些内容再发给浏览器. 浏览器根本不知道服务器发送的内容从哪里来的, 所以它的地址栏还是原来的地址. redirect 是服务端根据逻辑, 发送一个状态码, 告诉浏览器重新去请求那个地址. 所以地址栏显示的是新的 URL.
从数据共享来说
forward: 转发页面和转发到的页面可以共享 request 里面的数据. redirect: 不能共享数据.
从运用地方来说
forward: 一般用于用户登陆的时候, 根据角色转发到相应的模块. redirect: 一般用于用户注销登陆时返回主页面和跳转到其它的网站等
从效率来说
forward: 高. redirect: 低.
自动刷新(Refresh)
自动刷新不仅可以实现一段时间之后自动跳转到另一个页面, 还可以实现一段时间之后自动刷新本页面 Servlet 中通过 HttpServletResponse 对象设置 Header 属性实现自动刷新例如:
Response.setHeader("Refresh","1000;URL=http://localhost:8080/servlet/example.htm");
其中 1000 为时间, 单位为毫秒 URL 指定就是要跳转的页面(如果设置自己的路径, 就会实现没过一秒自动刷新本页面一次)
Servlet 与线程安全
Servlet 不是线程安全的, 多线程并发的读写会导致数据不同步的问题 解决的办法是尽量不要定义 name 属性, 而是要把 name 变量分别定义在 doGet()和 doPost()方法内虽然使用 synchronized(name){}语句块可以解决问题, 但是会造成线程的等待, 不是很科学的办法 注意: 多线程的并发的读写 Servlet 类属性会导致数据不同步但是如果只是并发地读取属性而不写入, 则不存在数据不同步的问题因此 Servlet 里的只读属性最好定义为 final 类型的
参考: javaweb 整合开发王者归来 P92
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 程序时经常需要修改 JSPTomcat 能够自动检测到 JSP 程序的改动如果检测到 JSP 源代码发生了改动 Tomcat 会在下次客户端请求 JSP 时重新编译 JSP, 而不需要重启 Tomcat 这种自动检测功能是默认开启的, 检测改动会消耗少量的时间, 在部署 Web 应用的时候可以在 web.xml 中将它关掉
参考: javaweb 整合开发王者归来 P97
JSP 有哪些内置对象? 作用分别是什么?
JSP 内置对象 - CSDN 博客
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]) : 返回和请求相关 Session
getServerName() : 获取服务器的名字
getServletPath(): 获取客户端所请求的脚本文件的路径
getServerPort(): 获取服务器的端口号
removeAttribute(String name): 删除请求中的一个属性
request.getAttribute()和 request.getParameter()有何区别?
从获取方向来看:
getParameter()是获取 POST/GET 传递的参数值;
getAttribute()是获取对象容器中的数据值;
从用途来看:
getParameter 用于客户端重定向时, 即点击了链接或提交按扭时传值用, 即用于在用表单或 url 重定向传值时接收数据用
getAttribute 用于服务器端重定向时, 即在 sevlet 中使用了 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 中的四种作用域
JSP 中的四种作用域包括 pagerequestsession 和 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 c =new Cookie("name","value"); // 创建 Cookie
- c.setMaxAge(60*60*24); // 设置最大时效, 此处设置的最大时效为一天
- response.addCookie(c); // 把 Cookie 放入到 HTTP 响应中
从客户端读取 Cookie
- String name ="name";
- Cookie[]cookies =request.getCookies();
- if(cookies !=null){
- for(int i= 0;i<cookies.length;i++){
- Cookie cookie =cookies[i];
- if(name.equals(cookis.getName()))
- //something is here.
- //you can get the value
- cookie.getValue();
- }
- }
优点: 数据可以持久保存, 不需要服务器资源, 简单, 基于文本的 Key-Value
缺点: 大小受到限制, 用户可以禁用 Cookie 功能, 由于保存在本地, 有一定的安全风险
URL 重写
在 URL 中添加用户会话的信息作为请求的参数, 或者将唯一的会话 ID 添加到 URL 结尾以标识一个会话
优点: 在 Cookie 被禁用的时候依然可以使用
缺点: 必须对网站的 URL 进行编码, 所有页面必须动态生成, 不能用预先记录下来的 URL 进行访问
3. 隐藏的表单域
<input type="hidden" name ="session" value="..."/>
优点: Cookie 被禁时可以使用
缺点: 所有页面必须是表单提交之后的结果
HttpSession
在所有会话跟踪技术中, HttpSession 对象是最强大也是功能最多的当一个用户第一次访问某个网站时会自动创建 HttpSession, 每个用户可以访问他自己的 HttpSession 可以通过 HttpServletRequest 对象的 getSession 方 法获得 HttpSession, 通过 HttpSession 的 setAttribute 方法可以将一个值放在 HttpSession 中, 通过调用 HttpSession 对象的 getAttribute 方法, 同时传入属性名就可以获取保存在 HttpSession 中的对象与上面三种方式不同的 是, HttpSession 放在服务器的内存中, 因此不要将过大的对象放在里面, 即使目前的 Servlet 容器可以在内存将满时将 HttpSession 中的对象移到其他存储设备中, 但是这样势必影响性能添加到 HttpSession 中的值可以是任意 Java 对象, 这个对象最好实现了 Serializable 接口, 这样 Servlet 容器在必要的时候可以将其序列化到文件中, 否则在序列化时就会出现异常
Cookie 和 Session 的的区别?
由于 HTTP 协议是无状态的协议, 所以服务端需要记录用户的状态时, 就需要用某种机制来识具体的用户, 这个机制就是 Session. 典型的场景比如购物车, 当你点击下单按钮时, 由于 HTTP 协议无状态, 所以并不知道是哪个用户操作的, 所以服务端要为特定的用户创建了特定的 Session, 用用于标识这个用户, 并且跟踪用户, 这样才知道购物车里面有几本书这个 Session 是保存在服务端的, 有一个唯一标识在服务端保存 Session 的方法很多, 内存数据库文件都有集群的时候也要考虑 Session 的转移, 在大型的网站, 一般会有专门的 Session 服务器集群, 用来保存用户会话, 这个时候 Session 信息都是放在内存的, 使用一些缓存服务比如 Memcached 之类的来放 Session
思考一下服务端如何识别特定的客户? 这个时候 Cookie 就登场了每次 HTTP 请求的时候, 客户端都会发送相应的 Cookie 信息到服务端实际上大多数的应用都是用 Cookie 来实现 Session 跟踪的, 第一次创建 Session 的时候, 服务端会在 HTTP 协议中告诉客户端, 需要在 Cookie 里面记录一个 Session ID, 以后每次请求把这个会话 ID 发送到服务器, 我就知道你是谁了有人问, 如果客户端的浏览器禁用了 Cookie 怎么办? 一般这种情况下, 会使用一种叫做 URL 重写的技术来进行会话跟踪, 即每次 HTTP 交互, URL 后面都会被附加上一个诸如 sid=xxxxx 这样的参数, 服务端据此来识别用户
Cookie 其实还可以用在一些方便用户的场景下, 设想你某次登陆过一个网站, 下次登录的时候不想再次输入账号了, 怎么办? 这个信息可以写到 Cookie 里面, 访问网站的时候, 网站页面的脚本可以读取这个信息, 就自动帮你把用户名给填了, 能够方便一下用户这也是 Cookie 名称的由来, 给用户的一点甜头所以, 总结一下: Session 是在服务端保存的一个数据结构, 用来跟踪用户的状态, 这个数据可以保存在集群数据库文件中; Cookie 是客户端保存用户信息的一种机制, 用来记录用户的一些信息, 也是实现 Session 的一种方式
参考:
https://www.zhihu.com/question/19786827/answer/28752144
javaweb 整合开发王者归来 P158 Cookie 和 Session 的比较
2018/3/31 20:45
现在寝室一片漆黑, 趁着电脑还有电把之前学习 JavaWeb 基础总结的东西在这里分享一下今天停了一天电, 现在这个电还没来电电脑快没电了, 大家再见 这些只是 JavaWeb 基础知识的一部分, 后面会持续更新
分享一下现在寝室的情景, 还没来电, 全是黑的:
来源: https://juejin.im/post/5abf6c1b6fb9a028bd4c705f