1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-07-20 03:13:00 +08:00
Java-Interview-Guide/docs/java/J2EE基础知识.md
2019-03-25 17:19:36 +08:00

306 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- MarkdownTOC -->
- [Servlet总结](#servlet总结)
- [阐述Servlet和CGI的区别?](#阐述servlet和cgi的区别)
- [CGI的不足之处:](#cgi的不足之处)
- [Servlet的优点](#servlet的优点)
- [Servlet接口中有哪些方法及Servlet生命周期探秘](#servlet接口中有哪些方法及servlet生命周期探秘)
- [get和post请求的区别](#get和post请求的区别)
- [什么情况下调用doGet\(\)和doPost\(\)](#什么情况下调用doget和dopost)
- [转发Forward和重定向Redirect的区别](#转发forward和重定向redirect的区别)
- [自动刷新\(Refresh\)](#自动刷新refresh)
- [Servlet与线程安全](#servlet与线程安全)
- [JSP和Servlet是什么关系](#jsp和servlet是什么关系)
- [JSP工作原理](#jsp工作原理)
- [JSP有哪些内置对象、作用分别是什么](#jsp有哪些内置对象、作用分别是什么)
- [Request对象的主要方法有哪些](#request对象的主要方法有哪些)
- [request.getAttribute\(\)和 request.getParameter\(\)有何区别](#requestgetattribute和-requestgetparameter有何区别)
- [include指令include的行为的区别](#include指令include的行为的区别)
- [JSP九大内置对象七大动作三大指令](#jsp九大内置对象七大动作三大指令)
- [讲解JSP中的四种作用域](#讲解jsp中的四种作用域)
- [如何实现JSP或Servlet的单线程模式](#如何实现jsp或servlet的单线程模式)
- [实现会话跟踪的技术有哪些](#实现会话跟踪的技术有哪些)
- [Cookie和Session的的区别](#cookie和session的的区别)
<!-- /MarkdownTOC -->
## 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所有动态加载的类可以实现对网络协议以及请求解码的共享大大降低了工作量。
4Servlet能直接和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方法和destroy方法只会执行一次service方法客户端每次请求Servlet都会执行**。Servlet中有时会用到一些需要初始化与销毁的资源因此可以把初始化资源的代码放入init方法中销毁资源的代码放入destroy方法中这样就不需要每次处理客户端的请求都要初始化与销毁资源。
参考《javaweb整合开发王者归来》P81
## get和post请求的区别
> 网上也有文章说get和post请求实际上是没有区别大家可以自行查询相关文章参考文章[https://www.cnblogs.com/logsharing/p/8448446.html](https://www.cnblogs.com/logsharing/p/8448446.html),知乎对应的问题链接:[get和post区别](https://www.zhihu.com/question/28586791))!我下面给出的只是一种常见的答案。
①get请求用来从服务器上获得资源而post是用来向服务器提交数据
②get将表单中数据按照name=value的形式添加到action 所指向的URL 后面,并且两者使用"?"连接,而各个变量之间使用"&"连接post是将表单中的数据放在HTTP协议的请求头或消息体中传递到action所指向URL
③get传输的数据要受到URL长度限制最大长度是 2048 个字符而post可以传输大量的数据上传文件通常要使用post方式
④使用get时参数会显示在地址栏上如果这些数据不是敏感数据那么可以使用get对于敏感数据还是应用使用post
⑤get使用MIME类型application/x-www-form-urlencoded的URL编码也叫百分号编码文本的格式传递参数保证被传送的参数由遵循规范的文本组成例如一个空格的编码是"%20"。
补充GET方式提交表单的典型应用是搜索引擎。GET方式就是被设计为查询用的。
还有另外一种回答。推荐大家看一下:
- https://www.zhihu.com/question/28586791
- https://mp.weixin.qq.com/s?__biz=MzI3NzIzMzg3Mw==&mid=100000054&idx=1&sn=71f6c214f3833d9ca20b9f7dcd9d33e4#rd
## 什么情况下调用doGet()和doPost()
Form标签里的method的属性为get时调用doGet()为post时调用doPost()。
## 转发(Forward)和重定向(Redirect)的区别
**转发是服务器行为,重定向是客户端行为。**
**转发Forword**
通过RequestDispatcher对象的forwardHttpServletRequest request,HttpServletResponse response方法实现的。RequestDispatcher可以通过HttpServletRequest 的getRequestDispatcher()方法获得。例如下面的代码就是跳转到login_success.jsp页面。
```java
request.getRequestDispatcher("login_success.jsp").forward(request, response);
```
**重定向Redirect** 是利用服务器返回的状态码来实现的。客户端浏览器请求服务器的时候,服务器会返回一个状态码。服务器通过 `HttpServletResponse``setStatus(int status)` 方法设置状态码。如果服务器返回301或者302则浏览器会到新的网址重新请求该资源。
1. **从地址栏显示来说**
forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.
redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.
2. **从数据共享来说**
forward:转发页面和转发到的页面可以共享request里面的数据.
redirect:不能共享数据.
3. **从运用地方来说**
forward:一般用于用户登陆的时候,根据角色转发到相应的模块.
redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等
4. 从效率来说
forward:高.
redirect:低.
## 自动刷新(Refresh)
自动刷新不仅可以实现一段时间之后自动跳转到另一个页面还可以实现一段时间之后自动刷新本页面。Servlet中通过HttpServletResponse对象设置Header属性实现自动刷新例如
```java
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类型的。
参考《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工作原理](https://user-gold-cdn.xitu.io/2018/3/31/1627bee073079a28?w=675&h=292&f=jpeg&s=133553)
由于JSP只会在客户端第一次请求的时候被编译 因此第一次请求JSP时会感觉比较慢之后就会感觉快很多。如果把服务器保存的class文件删除服务器也会重新编译JSP。
开发Web程序时经常需要修改JSP。Tomcat能够自动检测到JSP程序的改动。如果检测到JSP源代码发生了改动。Tomcat会在下次客户端请求JSP时重新编译JSP而不需要重启Tomcat。这种自动检测功能是默认开启的检测改动会消耗少量的时间在部署Web应用的时候可以在web.xml中将它关掉。
参考《javaweb整合开发王者归来》P97
## JSP有哪些内置对象、作用分别是什么
[JSP内置对象 - CSDN博客 ](http://blog.csdn.net/qq_34337272/article/details/64310849 )
JSP有9个内置对象
- request封装客户端的请求其中包含来自GET或POST请求的参数
- response封装服务器对客户端的响应
- pageContext通过该对象可以获取其他对象
- session封装用户会话的对象
- application封装服务器运行环境的对象
- out输出服务器响应的输出流对象
- configWeb应用的配置对象
- pageJSP页面本身相当于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 地址" %>
i**nclude动作** <jsp:include>动作元素用来包含静态和动态的文件。该动作把指定文件插入正在生成的页面。语法格式如下:
<jsp:include page="相对 URL 地址" flush="true" />
## JSP九大内置对象七大动作三大指令
[JSP九大内置对象七大动作三大指令总结](http://blog.csdn.net/qq_34337272/article/details/64310849)
## 讲解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实例这种实践将导致严重的性能问题服务器的内存压力很大还会导致频繁的垃圾回收所以通常情况下并不会这么做。
## 实现会话跟踪的技术有哪些
1. **使用Cookie**
向客户端发送Cookie
```java
Cookie c =new Cookie("name","value"); //创建Cookie
c.setMaxAge(60*60*24); //设置最大时效,此处设置的最大时效为一天
response.addCookie(c); //把Cookie放入到HTTP响应中
```
从客户端读取Cookie
```java
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功能由于保存在本地有一定的安全风险。
2. URL 重写
在URL中添加用户会话的信息作为请求的参数或者将唯一的会话ID添加到URL结尾以标识一个会话。
**优点:** 在Cookie被禁用的时候依然可以使用
**缺点:** 必须对网站的URL进行编码所有页面必须动态生成不能用预先记录下来的URL进行访问。
3.隐藏的表单域
```html
<input type="hidden" name ="session" value="..."/>
```
**优点:** Cookie被禁时可以使用
**缺点:** 所有页面必须是表单提交之后的结果。
4. HttpSession
在所有会话跟踪技术中HttpSession对象是最强大也是功能最多的。当一个用户第一次访问某个网站时会自动创建 HttpSession每个用户可以访问他自己的HttpSession。可以通过HttpServletRequest对象的getSession方 法获得HttpSession通过HttpSession的setAttribute方法可以将一个值放在HttpSession中通过调用 HttpSession对象的getAttribute方法同时传入属性名就可以获取保存在HttpSession中的对象。与上面三种方式不同的 是HttpSession放在服务器的内存中因此不要将过大的对象放在里面即使目前的Servlet容器可以在内存将满时将HttpSession 中的对象移到其他存储设备中但是这样势必影响性能。添加到HttpSession中的值可以是任意Java对象这个对象最好实现了 Serializable接口这样Servlet容器在必要的时候可以将其序列化到文件中否则在序列化时就会出现异常。
## Cookie和Session的的区别
1. 由于HTTP协议是无状态的协议所以服务端需要记录用户的状态时就需要用某种机制来识具体的用户这个机制就是Session.典型的场景比如购物车当你点击下单按钮时由于HTTP协议无状态所以并不知道是哪个用户操作的所以服务端要为特定的用户创建了特定的Session用用于标识这个用户并且跟踪用户这样才知道购物车里面有几本书。这个Session是保存在服务端的有一个唯一标识。在服务端保存Session的方法很多内存、数据库、文件都有。集群的时候也要考虑Session的转移在大型的网站一般会有专门的Session服务器集群用来保存用户会话这个时候 Session 信息都是放在内存的使用一些缓存服务比如Memcached之类的来放 Session。
2. 思考一下服务端如何识别特定的客户这个时候Cookie就登场了。每次HTTP请求的时候客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的第一次创建Session的时候服务端会在HTTP协议中告诉客户端需要在 Cookie 里面记录一个Session ID以后每次请求把这个会话ID发送到服务器我就知道你是谁了。有人问如果客户端的浏览器禁用了 Cookie 怎么办一般这种情况下会使用一种叫做URL重写的技术来进行会话跟踪即每次HTTP交互URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。
3. Cookie其实还可以用在一些方便用户的场景下设想你某次登陆过一个网站下次登录的时候不想再次输入账号了怎么办这个信息可以写到Cookie里面访问网站的时候网站页面的脚本可以读取这个信息就自动帮你把用户名给填了能够方便一下用户。这也是Cookie名称的由来给用户的一点甜头。所以总结一下Session是在服务端保存的一个数据结构用来跟踪用户的状态这个数据可以保存在集群、数据库、文件中Cookie是客户端保存用户信息的一种机制用来记录用户的一些信息也是实现Session的一种方式。
参考:
https://www.zhihu.com/question/19786827/answer/28752144
《javaweb整合开发王者归来》P158 Cookie和Session的比较