阿里技术专家深刻讲解,一文把Servlet整的明明白白

System.out.println("统一资源定位符:" + request.getRequestURL());html

System.out.println("协议和版本:" + request.getProtocol());

    System.out.println("当前项目地址:" + request.getContextPath());



    // 获得一个请求头

    System.out.println("获得host的请求头值:" + request.getHeader("host"));

}

}java

复制代码git

3.三、请求参数乱码问题(POST)

------------------



### 3.3.一、请求参数产生乱码的缘由



? 在浏览器发送数据给服务器的时候,**使用 utf-8 编码**,但服务器解码默认使用 ISO-8859-1 解码:欧洲码,不支持汉字的。



? **若是是 GET 请求且 Tomcat 版本大于8.0.5,则不须要考虑乱码问题,不然 GET 请求也须要考虑乱码问题。**



### 3.3.二、POST方式乱码解决方案



1.  解决方法:**request.setCharacterEncoding("utf-8") 设置请求参数的编码为UTF-8。**

2.  代码位置:设置请求的编码这句话必定放在获取请求参数以前。

3.  页面的编码:这个编码必定要与页面的编码相同。若是页面使用的是 GBK,则这里也要用GBK。



4、响应对象

======



4.一、HttpServletResponse对象概述

---------------------------



? HttpServletResponse 是一个接口,该接口的实现类对象称为响应对象,**用于响应数据(响应行,响应头,响应体)给浏览器**。HttpServletResponse 接口包含了大量的方法。由 Tomcat 去实现这个对象,而且在 servlet 启动的时候调用 service() 将请求对象和响应对象传递进来了。咱们在 service 方法中直接使用便可。



4.二、响应数据相关方法

------------



| 响应体相关的方法 | 功能描述 |

| --- | --- |

| OutputStream getOutputStream() | 若是服务器端返回的是二进制数据  

则使用这个方法,好比图片 |

| PrintWriter getWriter() | 若是服务器端返回的是字符的文本数据,使用这个方法 |

@WebServlet(urlPatterns = "/response")web

public class ResponseServlet extends HttpServlet {面试

@Override

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    // 得到字符打印流对象

    PrintWriter out = response.getWriter();

    // 响应数据给浏览器显示

    out.print("<h1 style='color:red'>hello browser<h1>");

}

}跨域

复制代码数组

4.三、响应内容中文乱码问题

--------------



### 4.3.一、乱码缘由



? 由于 Tomcat 中响应体默认的是欧洲码表,ISO-8859-1 不支持中文。



### 4.3.二、解决办法



4.3.二、方法一



? **在得到打印流对象以前,经过下面方法设置打印流的编码为utf-8**



| response方法 | 说明 |

| --- | --- |

| response.setCharacterEncoding("字符集") | 用于设置响应体的字符集  

设置打印流使用的码表 |

@WebServlet(urlPatterns = "/response")浏览器

public class ResponseServlet extends HttpServlet {服务器

@Override

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    // 设置打印流编码

    response.setCharacterEncoding("utf-8");

    // 得到字符打印流对象

    PrintWriter out = response.getWriter();

    // 响应数据给浏览器显示

    out.print("<h1 style='color:red'>你好 browser<h1>");

}

}session

复制代码

4.3.三、方法二



? **经过下面方法告诉浏览器返回数据类型和编码**



| 响应对象的方法 | 功能描述 |

| --- | --- |

| void setContentType(String type) | 1\. 告诉浏览器返回内容类型  

2\. 设置打印流编码  

**注意: 必须在获取流以前设置,不然无效** |

@WebServlet(urlPatterns = "/response")

public class ResponseServlet extends HttpServlet {

@Override

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    // 设置打印流编码

    // response.setCharacterEncoding("utf-8");



    // 告诉浏览器返回内容类型并设置打印流编码

    response.setContentType("text/html;charset=utf-8");

    // 得到字符打印流对象

    PrintWriter out = response.getWriter();

    // 响应数据给浏览器显示

    out.print("<h1 style='color:red'>你好 browser<h1>");

}

}

复制代码

5、JSP

=====



5.一、JSP的做用

----------



? JSP——Java Server Page运行在服务器端的 Java 页面,之前学习的 HTML 运行在浏览器端。JSP 是运行在服务器上,最终仍是解析成静态的HTML,运行在浏览器。咱们在浏览器上看到的HTML页面,实际上是 JSP 在服务器上运行的结果。



? **JSP 的主要做用是代替 Servlet 程序回传 html 页面的数据。由于 Servlet 程序回传 html 页面数据是一件很是繁锁的事情。开发成本和维护成本都极高。**



![image-20200514095259063](https://img-blog.csdnimg.cn/img_convert/55a0c415785f7fdf55b35fa2e8e9630d.png)



5.二、JSP的优点

----------



| 技术 | 特色 |

| --- | --- |

| HTML | 静态页面 优势:方便页面美化操做,写JS脚本和CSS代码都比较方便。  

缺点:不能写动态的内容。 |

| Servlet | 运行在服务器上小 Java 程序  

优势:制做动态内容  

缺点:不方便写 HTML 以及 CSS 和 JS 代码 |

| JSP | JSP = HTML + Servlet  

特色:既有 HTML 的优势:方便美化和编写 JS 代码。  

又有 Servlet 优势:能够在页面写 Java 代码,能够制做动态内容(不建议)。 |



5.三、JSP的原理

----------



? \*\*JSP页面本质上是一个 Servlet 程序。\*\*当咱们第一次访问 jsp 页面的时候。Tomcat 服务器会帮咱们把 jsp 页面翻译成为一个 java 源文件。而且对它进行编译成为.class 字节码程序。咱们打开 java 源文件不难发现其里面的内容是:



![image-20210116212753515](https://img-blog.csdnimg.cn/img_convert/34736f701195e36b8036b4c2269b3366.png)



? 咱们跟踪原代码发现,HttpJspBase 类。它直接地继承了 HttpServlet 类。也就是说。jsp 翻译出来的 java 类,它间接了继承了 HttpServlet 类。也就是说,翻译出来的是一个 Servlet 程序。



? ![image-20210116212815402](https://img-blog.csdnimg.cn/img_convert/e7cfc50dae1fb00afca7e225bc646fdc.png)



? 翻译出来的 Servlet 程序的源代码,不难发现。其底层实现,也是经过输出流。把 html 页面数据回传



给客户端。

out.write("\r\n");

out.write("\r\n");

out.write("<html>\r\n");

out.write("<head>\r\n");

out.write("

<title>Title</title>\r\n");

out.write("</head>\r\n");

out.write("<body>\r\n");

out.write("

a.jsp 页面\r\n");

out.write("</body>\r\n");

out.write("</html>\r\n");

复制代码

5.四、JSP运行过程

-----------



? JspServlet 首先会将 jsp 文件代码翻译成 Servlet 的 Java 代码,而后再编译成字节码文件执行,其底层就是一个 Servlet。



![image-20200424093408316](https://img-blog.csdnimg.cn/img_convert/c9d2725fa5d1d4a7d35155e839460bdb.png)



1.  浏览器请求 JSP 页面,Tomcat 中的 JspServlet 会先 JSP 文件翻译成 Servlet 文件:xxx\_jsp.java。

2.  将 xxx\_jsp.java 文件编译产生字节码文件:xxx\_jsp.class。

3.  加载字节码文件 xxx\_jsp.class 并建立 xxx\_jsp 对象。

4.  调用 xxx\_jsp 的 service 方法处理请求并响应数据。



? **浏览器第一次访问 JSP 的时候,由 Tomcat 将 JSP 翻译成了 Servlet,而且编译成字节码文件,只生成1次。若是这期间修改了JSP内容,就会从新翻译。**



6、转发和重定向

========



6.一、转发和重定向的做用

-------------



? 用于 web 组件的跳转,从A 组件跳到另外一个组件B。



6.二、转发

------



![image-20210116214138803](https://img-blog.csdnimg.cn/img_convert/2aaf0d0a627d45459061fe0ec3461923.png)



### 6.2.一、跳转位置



? 请求转发是指,服务器收到请求后,从一次资源跳转到另外一个资源的操做叫请求转发。在服务器端进行的组件(资源)的跳转。



![image-20200424101847738](https://img-blog.csdnimg.cn/img_convert/63813ac9cbcd835797fbfa2da12b4cf5.png)



### 6.2.二、转发的方法

request.getRequestDispatcher("/要跳转到的地址").forward(request, response);

复制代码

6.三、重定向

-------



![image-20210116220209299](https://img-blog.csdnimg.cn/img_convert/578a593e1720e9e811703c2ef2d189d3.png)



### 6.3.一、跳转的位置



? 在浏览器端进行的页面(组件/资源)跳转。



![image-20200424102524457](https://img-blog.csdnimg.cn/img_convert/f61cd1965e7bf5829ab8bdbf4815618d.png)



### 6.3.二、重定向的方法

response.sendRedirect("要跳转的地址")

复制代码

6.四、转发和重定向的区别

-------------



| 区别 | 转发 forward | 重定向 redirect |

| --- | --- | --- |

| 目录 | 能够访问WEB-INF目录下的资源 | 不能够访问WEB-INF目录下的资源 |

| 地址栏 | 地址栏不会发生变化,仍是上一个地址 | 会变化,显示新的地址 |

| 跳转位置 | 在服务端进行跳转 | 在浏览器端跳转 |

| 请求对象(域) | 请求域数据不会丢失,由于是同一个请求 | 请求域数据会丢失,由于不是同一个请求 |



6.五、注意

------



1.  不管是重定向仍是转发,后续代码都会执行,但通常转发或重定向后面不会有代码,没有执行的意义了,由于不论是转发仍是重定向浏览器最终显示的都是跳转后页面的数据。

2.  若是须要保留请求域中的数据,必须使用转发。

3.  若是须要跳转到WEB-INF目录中的资源,必须使用转发。

4.  若是须要跨域,必须使用重定向。



7、三大做用域

=======



7.一、什么是做用域

----------



? 用于 Servlet 之间数据共享的服务器内存区域,做用域结构是一个Map<String, Object>。



![img01](https://img-blog.csdnimg.cn/img_convert/d19fb1cbca96507bcbab180fb307e066.png)



7.二、做用域类型

---------



| 做用域 | 类型 | 做用范围 |

| --- | --- | --- |

| 请求域 | HttpServletRequest | 只在同一次请求中起做用 |

| 会话域 | HttpSession | 同一个会话中起做用  

浏览器第1次访问服务器直到浏览器关闭  

的整个过程称为1次会话 |

| 上下文域 | ServletContext | 同一个应用中起做用  

服务器启动直到服务器关闭的整个过程都起做用 |



7.三、做用域方法

---------



| 与做用域有关的方法 | 做用 |

| --- | --- |

| Object getAttribute("键") | 从中获得一个值 |

| void setAttribute("键",Object数据) | 向做用域中存储键值对数据 |

| void removeAttribute("键") | 删除做用域中的键值对数据 |



7.四、如何选择做用域

-----------



? **先考虑做用范围小的做用域,若是小做用范围的做用域能知足需求就使用小做用范围的做用域。**



8、EL表达式

=======



8.一、什么是EL表达式

------------



? EL 表达式的全称是:`Expression Language`。是表达式语言。



? EL 表达式主要是代替 jsp 页面中的表达式脚本在 jsp 页面中进行数据的输出。由于 EL 表达式在输出数据的时候,要比 jsp 的表达式脚本要简洁不少。



8.二、EL表达式运算

-----------



### 8.2.一、算数运算



| 算术运算符 | 说明 | 举例 | 结果 |

| --- | --- | --- | --- |

| + | 加法 | ${12+18} | 30 |

| \- | 减法 | ${18-8} | 10 |

| \* | 乘法 | ${12\*12} | 144 |

| /(div) | 除法 | 6/3或{6/3}或6/3或{6 div 3} | 2 |

| %(mod) | 取模 | {10%3} 或{10 mod 3} | 1 |



### 8.2.二、逻辑运算



| 逻辑运算符 | 说明 | 举例 | 结果 |

| --- | --- | --- | --- |

| && 或 and | 与运算 | { 12 == 12 && 12 < 11 } 或 { 12 == 12 and 12 < 11 } | false |

| | 或 or | 或运算 | 12==12∥∥12<11或{ 12 = = 12 \\|\\| 12<11}或 12==12∥∥12<11或{12= =12 or 12<11} | true |

| ! 或 not | 取反运算 | !true后{!true} 后 !true后{not true} | false |



### 8.2.三、关系运算



| 关系运算 | 说明 | 举例 | 结果 |

| --- | --- | --- | --- |

| \== 或 eq | 等于 | 5==5或{5 == 5} 或 5==5或{5 eq 5} | true |

| != 或 ne | 不等于 | 5!=5或{5 !=5} 或 5!=5或{5 ne 5} | false |

| < 或 lt | 小于 | 3<5或{3 < 5} 或 3<5或{3 lt 5} | true |

| \> 或 gt | 大于 | 2>10或{2 > 10} 或 2>10或{2 gt 10} | false |

| <= 或 le | 小于等于 | 5<=12或{ 5 <= 12 } 或 5<=12或{ 5 le 12 } | true |

| \>= 或 ge | 大于等于 | 3>=5或{ 3 >= 5 }或 3>=5或{ 3 ge 5 } | false |



### 8.2.四、三元运算



? `表达式 1?表达式 2:表达式 3`



? 若是表达式 1 的值为真,返回表达式 2 的值,若是表达式 1 的值为假,返回表达式 3 的值。



![img11](https://img-blog.csdnimg.cn/img_convert/e30e91d36d1838b68abf7a91e5c37355.png)



### 8.2.五、判空运算



? 判空:判断的是内容是否为空,不是对象是否为空。



? ![img12](https://img-blog.csdnimg.cn/img_convert/c1dc13b32960ebb0e6b564843c30adb7.png)



8.三、EL 从四个做用域中取值

----------------



? **EL 获取数据的方式是从 4 个做用域对象中,从小到大的去获取**,若是须要指定做用域获取数据,可以使用如下 EL 的内置对象来指定。



### 8.3.一、PageContext 对象



? JSP 本质是 Servlet,但比 Servlet 多了一个做用域:**页面域**,在 JSP 中有四大做用域。页面域是只在一个JSP页面中起做用,不一样的JSP之间不能实现数据的共享,比请求域范围还要小。



| PageContext 操做有关的方法 | 说明 |

| --- | --- |

| void setAttribute(String key, Object value) | 向页面域中添加键和值 |

| Object getAttribute(String key) | 从页面域中获得值 |

| void removeAttribute(String key) | 删除四个域中同名的键 |

| Object findAttribute(String key) | 自动从四个做用域中去查某个键,  

从小到大的范围来查找,若是找到就中止。  

若是没有找到,返回null |

<%

//向页面域中添加一个字符串    

pageContext.setAttribute("name","我是页面域");

%>

复制代码

### 8.3.二、 EL 指定域获取数据



| 做用域 | EL的写法 |

| --- | --- |

| 页面域 | ${pageScope.键名} |

| 请求域 | ${requestScope.键名} |

| 会话域 | ${sessionScope.键名} |

| 上下文域 | ${applicationScope.键名} |

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<title>EL指定域获取数据</title>
<%

    // 向页面域中添加一个字符串

    pageContext.setAttribute("name", "页面域");

    // 请求域

    request.setAttribute("name", "请求域");

    // 会话域

    session.setAttribute("name", "会话域");

    // 上下文域

    application.setAttribute("name", "上下文域");

%>

    

从页面域获取:${pageScope.name}

<hr>



从请求域获取:${requestScope.name}

<hr>



从会话域获取:${sessionScope.name}

<hr>



从上下文域获取:${applicationScope.name}

<hr>

	自动查找做用域获取:${name}

<hr>

复制代码

9、JSTL 标签库

==========



? JSTL 标签库 全称是指 JSP Standard Tag Library JSP 标准标签库。是一个不断完善的开放源代码的 JSP 标签库。EL 表达式主要是为了替换 jsp 中的表达式脚本,而标签库则是为了替换代码脚本。这样使得整个 jsp 页面变得更佳简洁。JSTL 由五个不一样功能的标签库组成。



| 功能范围 | URL | 前缀 |

| --- | --- | --- |

| **核心标签库** | [java.sun.com/jsp/jstl/co…](https://gitee.com/vip204888/java-p7) | c |

| 格式化 | [java.sun.com/jsp/jstl/fm…](https://gitee.com/vip204888/java-p7) | fmt |

| 函数 | [java.sun.com/jsp/jstl/fu…](https://gitee.com/vip204888/java-p7) | fn |



9.一、使用步骤

--------



### 9.1.一、导入jar包

taglibs-standard-impl-1.2.1.jar

taglibs-standard-spec-1.2.1.jar

复制代码

### 9.1.二、引入标签库

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

复制代码

### 9.1.三、使用标签



9.二、核心标签库经常使用标签

-------------



### 9.2.一、<c:if />



? 用于页面上单条件判断。



| 属性名 | 是否支持EL | 属性类型 | 属 性 描 述 |

| --- | --- | --- | --- |

| test | 支持,必须是 EL | boolean值 | EL 中条件为真则执行标签体内容  

注意:没有对应 else 标签 |

<%--

ii.<c:if />

if 标签用来作 if 判断。

test 属性表示判断的条件(使用 EL 表达式输出)

--%>

<c:if test="${ a == b }">

若是a等于b

</c:if>

<c:if test="${ a != b }">

若是a不等于b

</c:if>

复制代码

### 9.2.二、<c:choose>



? 用于多分支判断(多条件判断),相似于跟 switch ... case .... default 。



| 标签名 | 做用 |

| --- | --- |

| choose | 相似于 java 中swtich, choose只是一个容器,包含下面两个元素 |

| when | 能够出现多个,用于每一个判断条件,相似于 switch 中 case。有一个 test 属性,与 if 功能相同 |

| otherwise | 若是上面全部的条件都不知足,执行 otherwise 内容。相似于 switch 中 default |



### 9.2.三、<c:forEach>



? 用于遍历集合或数组(最为经常使用)。



| 属性名 | 是否支持EL | 属性类型 | 属性描述 |

| --- | --- | --- | --- |

| items | true | 数组或集合 | 使用 EL 表达式,表明集合或数组 |

| var | false | String | var 的变量名表明集合中的每个元素 |

| varStatus | false | String | 表明每一个元素的状态对象,  

一共有4个属性,属性的含义见下表 |



? varStatus属性表:



| 属性 | 数据类型 | 含义 |

| --- | --- | --- |

| index | int | 当前遍历到的这个元素索引号,从 0 开始 |

| **count** | int | 遍历到当前为止,一共遍历了多少个元素,从1 开始 |

| first | boolean | 若是当前遍历的是第1个元素,则返回true |

| last | boolean | 若是当前遍历的是最后1个元素,则返回true |

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<title>学生信息表</title>

<style>

    tr {

        text-align: center;

    }

</style>
<caption>学生信息列表</caption>

<tr>

    <th>序号</th>

    <th>学号</th>

    <th>姓名</th>

    <th>性别</th>

    <th>成绩</th>

</tr>



<%--

    forEach标签:用于JSP页面遍历集合和数组

        items属性:设置要遍历的集合或数组:通常从做用域中获取

        var属性:设置一个变量名:用来接收遍历到的每个元素



        varStatus属性:设置一个变量名:记录当前遍历元素的状态(状态对象)

            index 属性:当前遍历元素的在集合中的索引值:从0开始

            count 属性:遍历到当前元素为止已经遍历了多少个元素,从 1 开始

--%>

<c:forEach items="${stus}" var="stu" varStatus="status">

    <!-- 给偶数行设置背景颜色 -->

    <tr style="background-color:${status.count % 2 == 0 ? 'gray;' : ''}">

        <td>${status.count}</td>

        <td>${stu.id}</td>

        <td>${stu.name}</td>

        <td>${stu.gender? "男":"女"}</td>

        <td>${stu.score}</td>

    </tr>

</c:forEach>

复制代码

9.三、格式化标签库经常使用标签



# 最后

针对最近不少人都在面试,我这边也整理了至关多的面试专题资料,也有其余大厂的面经。但愿能够帮助到你们。

![image](https://upload-images.jianshu.io/upload_images/24613101-bd5471b3c4055df2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)



> 上述的面试题答案都整理成文档笔记。 也还整理了一些面试资料&最新2021收集的一些大厂的面试真题(都整理成文档,小部分截图)
>
> **资料领取方式:[点击这里免费获取](https://gitee.com/vip204888/java-p7)**

![image](https://upload-images.jianshu.io/upload_images/24613101-037ac3b223a0b02e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)




以上就是本文的所有内容,但愿对你们的学习有所帮助,也但愿你们多多支持。