Servlet(Server Applet)服务器的小程序。是用java编写的一个服务器程序,目的是和浏览器交互并且生成动态的web内容。Servlet广义上来讲指的是servlet接口,狭义上来讲指的是所有实现接口的实现类。
Servlet是指实现了Servlet接口类,Servlet运行于支持java的应用服务器(tomcat,Servlet是tomcat的一个组件)中。从原理上来讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务。

Servlet是Tomcat的一个组件。Servlet的功能需要依赖一个servlet-api.jar,这个包是由tomcat提供的。
Tomcat在初始化Servlet时,首先读取web.xml文件,根据web.xml文件中的参数信息初始化ServletConfig、ServletContext对象,同时帮助我们创建HttpServletRequest和HttpServletResponse对象一并交给Servlet实例,此时,Servlet就具有了相关的功能。
1.javax.servlet:定义了servlet接口、GenericServlet抽象类等相关的通用接口和类。
2.javax.servlet.http: 主要定义了与HTTP协议相关的HttpServlet类,HttpServletRequest接口和HttpServletResponse接口。
3.javax.servlet.annotation:包含标注servlet,Filter,Listener的标注。它还为被标注元件定义元数据。
4.javax.servlet.descriptor:提供程序化登录Web应用程序的配置信息的类型。


在HttpServlet的API中,新增了两个特殊的方法doGet和doPost,这两个方法是对servlet方法的拆分,目的是希望不同的请求方式使用不同的方法处理。
这让大家联想到表单的两种常用提交方式get和post,如果是get提交方式则使用doGet方法处理,如果时post提交方式则使用doPost方法处理。
而service方法可以处理任何类型的请求,当我们去查看HttpServlet中service方法的源码,不难发现内部也通过对method请求方式做了验证决定调用doGet或doPost方法,所以三个方法之间的关系如下:
结论:
二者选择其一
Get:通过Url传递参数,Url与参数之间用?隔开,多个参数之间用&隔开,也是表单的默认提交参数。

Post:所有操作对用户来说都是不可见的,相对于get方式更安全。

Get传送的数据量较小,这主要是因为受URL长度限制2kb-6kb;
Post传送的数据量较大,一般被默认为不受限制。
Get提交的信息能被缓存,请求保留在浏览器历史记录中
Post提交的数据一般不能被缓存,请求不会保留在浏览器历史中
Get:默认编码类型是:application/x-www-form-urlencoded;Tomcat8之前的版本,默认编码格式是iso-8859-1,从Tomcat8版本之后默认编码改为UTF-8,所以如果是Tomcat8及以上版本就不需要进行转码处理,如果是Tomcat7及之前版本可以使用以下进行转码:
String name = request.getParameter(“name”);
String encodingName = new String(name.getBytes(“iso-8859-1”),””utf-8”) ;
Post: 支持多种编码类型,application/x-www-form-urlencoded或multipart/form-data.可以使用以下方法进行转码:
Request.setCharacterEncoding(“utf-8”);
在这里顺便说一下响应的乱码处理方法:
Response.setContentType(“text/html;charset=utf-8”);
项目在实际开发过程中,会将整个项目从上到下分为表示层、业务逻辑层、数据访问层。三层开发是项目开发实践中典型的开发模式。
分层开发的目的:实现高内聚、低耦合。
各层的功能:
MVC模式(Model-view-controller)是软件工程中的一种软件架构模式,他把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。这种模式用于应用程序的分层开发。
Model(模型):模型代表一个存取数据的对象或JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
View(视图):试图代表模型包含的数据的可视化,即对Model数据的呈现。
Controller(控制器):控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化更新视图。他是视图与模型分离开。

Model不属于任何层,他可能在每个层中都会用到,是数据存储和传输的载体。V和C都属于表示层,所以在某些情况下,可以认为MVC模式是对表示层的进一步分层,通过C将数据显示与数据模型分类离,同样起到降低耦合性的作用,简化后续对程序的修改和扩展,并且是程序某一部分的重复利用成为可能。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="demo05?mark=insert">添加</a>
<a href="demo05?mark=query">查询</a>
<a href="demo05?mark=update">修改</a>
<a href="demo05?mark=delete">删除</a>
</body>
</html>
package com.ujiuye.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 多方法请求
* 一个servlet只有一个service方法,比如写项目,一个模块最低有增删改查4个功能
* 最低要创建5个servlet,项目有6个模块,30个servlet
*
* 用一个servlet去接收一个模块的所有请求
* UserServlet 去接收用户模块的所有请求
*
*/
public class Demo05Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//先去获取mark参数
String mark = req.getParameter("mark");
//常量放到前面判断 防止空指针异常
if("insert".equals(mark)) {
//说明是添加的功能
insert(req,resp);
}else if("query".equals(mark)) {
//查询
query(req,resp);
}else if("update".equals(mark)) {
//修改
update(req,resp);
}else if("delete".equals(mark)) {
//删除
delete(req,resp);
}
}
private void delete(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("删除的功能");
}
private void update(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("修改的功能");
}
private void query(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("查询的功能");
}
private void insert(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("执行添加的代码 调用service");
}
}
1、创建一个servlet继承httpservlet,重写init,service,destroy方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="demo06">测试servlet生命周期</a>
</body>
</html>
ackage com.ujiuye.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Demo06Servlet extends HttpServlet {
public Demo06Servlet() {
System.out.println("无参构造方法执行了");
}
@Override
public void init() throws ServletException {
//初始化方法 只会执行一次
System.out.println("init方法执行了");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//服务方法 可以执行多次
System.out.println("service方法执行了");
}
public void destroy() {
//销毁的方法 只会执行一次
System.out.println("destroy方法执行了");
}
}
2、第一次访问servlet,实例化servlet,执行init方法,执行service

3、第二次访问servlet

4、停止服务器

总结:
1、分为三个阶段
(1)初始化阶段 会执行init方法 只会执行一次
默认是在第一次访问servlet时进行执行,可以在web.xml进行配置,配置<load-on-startup> 让servlet随着tomcat的启动而进行 初始化,配置的值大于0即可,配置为负数就是默认情况,当多个 servlet配置了<load-on-startup>值越小的优先执行
(2)服务阶段 执行service方法 会执行多次
(3)销毁阶段 会执行destroy方法 只会执行一次 点击停止服务器
* 是通配符 例如:/hello、/admin/login、/*
/hello :<url-pattern>/hello<url-pattern>这个配置只拦截hello,其他的不拦截
/admin/login :层级目录的格式,请求的方式<url-pattern>/admin/login<url-pattern>
/* :拦截所有,无论是脚本、css、或者是单纯的一个页面,全部拦截
*.do 表示特定的拦截方式,只拦截action中带.do的url(do可以换成任意字符)
<url-pattern>*.do</url-pattern>
servlet本身很特殊,因为前台的URL都会进入service方法或doGet、doPost方法,那么这些URL基本很少使用统配的形式,最常用的两种方式就是:/hello、/admin/login,而*.do的方式很少用。
正常情况下同一个业务实体的功能会对应一个servlet,例如:
用户管理UserServlet(用户所有的CRUD都在这个Servlet中执行,和页面无关)
权限控制RoleServlet(权限所有CRUD都在这个Servlet中执行)
Request是由tomcat创建的。
Request对象是来获取请求信息的。
ServletRequest 接口 javax.servlet
|^继承
HttpServletRequest 子接口 javax.servlet.http
接收客户端的请求,获取请求中的信息。除了可以获取请求中携带的数据之外,还可以 获取比如主机地址、端口、请求方式、项目名称等一系列信息。
请求分类: 请求行、请求头、请求体。


请求行中,我们可以通过request对象的相应方法获取到比如协议名、服务名、端口号、项目名称、请求方式、参数列表等信息。
"协议名:" request.getScheme();
"服务器:" request.getServerName();
"端口号:" request.getServerPort();
"项目名:" request.getContextPath();
"请求方式:" request.getMethod();
"参数字符串:" request.getQueryString();
"项目名+具体地址:" request.getRequestURI();
"获取请求的URL:" request.getRequestURL();
"获取请求的URL:" request.getServletPath();
package com.ujiuye.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 请求头
* "协议名:" request.getScheme();
* "服务器:" request.getServerName();
* "端口号:" request.getServerPort();
* "项目名:" request.getContextPath();
* "请求方式:" request.getMethod();
* "参数字符串:" request.getQueryString();
* "项目名+具体地址:" request.getRequestURI();
* "获取请求的URL:" request.getRequestURL();
* "获取请求的URL:" request.getServletPath();
*/
@WebServlet("/demo09")
public class Demo09Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
String scheme = req.getScheme();
System.out.println("scheme = " + scheme);
String serverName = req.getServerName();
System.out.println("serverName = " + serverName);
int serverPort = req.getServerPort();
System.out.println("serverPort = " + serverPort);
String contextPath = req.getContextPath();
System.out.println("contextPath = " + contextPath);
String method = req.getMethod();
System.out.println("method = " + method);
String queryString = req.getQueryString();
System.out.println("queryString = " + queryString);
String uri = req.getRequestURI();
System.out.println("uri = " + uri);
StringBuffer url = req.getRequestURL();
System.out.println("url = " + url);
String servletPath = req.getServletPath();
System.out.println("servletPath = " + servletPath);
}
}
请求头是当前对用户发送的数据的描述信息。
请求头信息在请求的时候不需要程序员手动添加,是浏览器发送的时候已经处理好的。
如果想查看请求头信息,也可以在Servlet中通过getHeader方法获取。
获取请求头数据的方法:
| 方法名 | 描述 |
| String getHeader(String name) | 根据请求头的名称获取请求头信息 |
| Enumeration getHeaderNames() | 返回此请求包含的所有头名称的枚举 |
package com.ujiuye.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
/**
* 请求头
*/
@WebServlet("/demo10")
public class Demo10Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
//通过请求头的key获取对应的value
String host = req.getHeader("Host");
System.out.println("host = " + host);
//获取所有头的key
Enumeration<String> en = req.getHeaderNames();
//遍历
while (en.hasMoreElements()) {
String name = en.nextElement();
//通过name获取value
String value = req.getHeader(name);
System.out.println(name + "..." + value);
}
}
}
请求体就是请求中携带的数据,也就是我们需要获取的参数
获取请求参数的方法:
| 方法名 | 描述 |
| String getParameter(String name) | 根据参数名获取参数值 |
| String[] getParameterValues(String name) | 根据参数名获取参数值(可以是多个值) |
| Enumeration getPatameterNames() | 获取所有的参数名 |
| Map<String,String[]> getParameterMap() | 获取所有参数的map集合 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>请求体</title>
</head>
<body>
<!--
-->
<form action="demo11" method="get">
账号: <input type="text" name="username"> <br>
密码: <input type="password" name="password"> <br>
性别: <input type="radio" name="sex" value="男"> 男
<input type="radio" name="sex" value="女">女 <br>
爱好: <input type="checkbox" name="hobby" value="唱">唱
<input type="checkbox" name="hobby" value="跳">跳
<input type="checkbox" name="hobby" value="rap">rap
<input type="checkbox" name="hobby" value="打篮球">打篮球 <br>
学校: <select name="school">
<option value="小学">小学</option>
<option value="中学">中学</option>
<option value="大学">大学</option>
</select>
<br>
简介: <textarea name="mark" cols="30" rows="10"></textarea> <br>
<input type="submit" value="点我">
</form>
</body>
</html>
package com.ujiuye.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
/**
* 请求体
*/
@WebServlet("/demo11")
public class Demo11Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
//获取文本框、密码框、隐藏框、日期框
//通过name值获取value 没有传递参数获取的是""
String username = req.getParameter("username");
System.out.println("username = " + username);
//单选框 通过name值获取被选中单选框的value值 没有选中获取的是bull
String sex = req.getParameter("sex");
System.out.println("sex = " + sex);
//复选框 getParameterValues获取 没有选中获取的是null
String[] hobbies = req.getParameterValues("hobby");
System.out.println(Arrays.toString(hobbies));
//下拉列表 通过name值获取被选中option的value值
String school = req.getParameter("school");
System.out.println("school = " + school);
//简介 通过name值获取
String mark = req.getParameter("mark");
System.out.println("mark = " + mark);
System.out.println("-----------------------------------------------------------------------");
//一次获取所有的参数
Map<String, String[]> map = req.getParameterMap();
Set<String> set = map.keySet();
for (String key : set) {
System.out.println(key + "...." + Arrays.toString(map.get(key)));
}
System.out.println("-----------------------------------------------------------------------");
//获取所有的参数名
Enumeration<String> en = req.getParameterNames();
while (en.hasMoreElements()) {
System.out.println(en.nextElement());
}
}
}
Response是由tomcat创建的
Response对象是来设置响应信息
ServletResponse 接口
|^继承
HttpServletResponse 子接口
|^实现
org.apache.catalina.connector.ResponseFacade 实现类
针对页面发送的请求做出数据响应,向页面输出信息,包括文本、图片、视频等。
响应分类: 响应行、响应头、响应体。

响应行中包含的信息:可以通过开发者模式F12-Network查看

由上图可知,响应行中包含协议和状态码
(1)HTTP协议
HTTP协议的特点:
1、 简单快捷。客户端向服务器请求时,只需要传送请求方法和路径。
2、灵活。HTTP协议允许传送任意格式的数据。正在传输的类型由content-type标明。
3、 无连接(长连接)。每个请求都建立一个连接,请求处理完毕并发送至客户端之后就断开连接。这样明显有其缺点,就是在需要连续发送请求时,需要为每一个请求单独的在此建立连接,很浪费时间和资源。
于是HTTP协议1.1版本之后引入了可持续连接,也就是在每个请求处理完毕后,他不会立刻就断开连接,而是在等待一段时间,如果在此期间又有新的请求过来,那么等待时间刷新,如果没有,则等待时间完毕后,连接关闭。
4、 无状态。是指协议对于每次请求的处理没有记忆能力,他不知道之前是否已经访问过,不保留访问痕迹。主要目的是保证数据传输的安全性。
HTTP的版本:
0.9 -适用于各种数据信息的简洁快速协议,仅限于传输文本
1.0 -该协议对每一次请求/响应建立并拆除一次连接,不支持长连接
1.1 -在1.0版本的基础上支持长连接keep-alive
HTTPS:以安全为目标的HTTP通道,简单的讲是HTTP的安全版本,即HTTP下加入SSL层,简称HTTPS。
其中HTTPS的安全基础为SSL,因此通过它的传输内容都是经过SSl加密的,他的主要作用可以分为两种:
HTTP底层协议:TCP协议
TCP的特点:面向连接,保证可靠性
TCP三次握手,因为HTTP是基于TCP协议的,所以也可以认为是HTTP的三次握手:
第一次握手:客户端向服务器发送一个请求消息,服务端收到信息后知道自己与客户端是可以连接成功的;
第二次握手:此时客户端并不知道服务端是否已经接收到了他的请求,所以服务端接收到消息后要向客户端做出响应,客户端的到服务端的反馈后,才确定自己与服务器是可以连接上的。
第三次握手:客户端确认与服务器建立连接后,才开始向服务器发送数据。
(2)状态码
响应状态码200表示响应成功,不同的状态码代表不同的含义。
1xx -信息,服务器收到请求,需要请求者继续执行操作
2xx -成功,操作被成功接收并处理
3xx -重定向,需要进一步的操作已完成请求
4xx -客户端错误,请求包含语法错误或无法请求
5xx -服务器错误,服务器在处理请求的过程中发生了错误
几种常见的状态码:
200 请求和响应成功
404 客户端的错误、浏览器url地址写错误、tomcat没有启动、servlet没有拦截路径
500 服务器错误、后台代码有问题、查看控制台寻找错误信息、java代码或者jsp代码出错、空指针异常
案例实现:
package com.ujiuye.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/demo01")
public class Demo01Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//设置错误的状态码和提示消息 测试一下 一般不用
resp.sendError(500,"你自己写的烂代码心里没有b数吗?");
}
}
当我们在浏览器中打开network工具时,每一次的请求响应数据,都可以被捕捉到,而在内容中Response Headers中的的内容就是当前这一次请求响应的响应头信息。

package com.ujiuye.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/demo02")
public class Demo02Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setHeader("name","zhangsan");
resp.setHeader("name","lisi");
resp.addHeader("age","17");
resp.addHeader("age","18");
}
}
响应的数据就是响应体。响应对象response在返回数据、响应数据的时候,会将一些HTML、text、流数据等信息通过响应主体返回给页面,而响应体返回给页面,而响应体绝大多数都是文本类型。
响应数据需要通过流来进行数据传输,而response自带的流有两个:
Response.getWriter() ==>PrintWriter 输出文本信息
Response.getOutputStream ==> ServletOutputStream 输出字节信息
注意:这两个流不能同时共存
需求:演示两个流不能同时共存
案例实现:
package com.ujiuye.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/demo03")
public class Demo03Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
//设置请求和响应的字符集
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
/*//1、第一种响应流
PrintWriter w = resp.getWriter();
w.print("zhangsan");
//可以识别标签和样式
w.print("<h2 style='color:red;'>李四</h2>");*/
/*
2、第二种响应体 处理字节信息 处理字符没有优势
1、通过字符串的构造器将张三转成iso8859-1
2、配置tomcat的vm -Dfile.encoding=utf-8
才能在页面上看到汉字张三
*/
ServletOutputStream sos = resp.getOutputStream();
sos.print(new String("张三".getBytes(),"iso8859-1"));
}
}
案例:响应表格
package com.ujiuye.servlet;
import com.ujiuye.bean.Student;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
* 响应表格
*/
@WebServlet("/demo04")
public class Demo04Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
//设置请求和响应的字符集
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
List<Student> lists = new ArrayList<>();
lists.add(new Student(1,"张三1","男","吃饭","大学"));
lists.add(new Student(2,"张三2","男","吃饭","大学"));
lists.add(new Student(3,"张三3","男","吃饭","大学"));
lists.add(new Student(4,"张三4","男","吃饭","大学"));
lists.add(new Student(5,"张三5","男","吃饭","大学"));
lists.add(new Student(6,"张三6","男","吃饭","大学"));
PrintWriter w = resp.getWriter();
w.print("<table border=1 width=400px>");
w.print("<tr><td>学号</td><td>姓名</td><td>性别</td><td>爱好</td><td>学校</td></tr>");
//遍历lists集合 每遍历一次 拼接一行tr
for (Student stu : lists) {
w.print("<tr>");
w.print("<td>" + stu.getSid() + "</td>");
w.print("<td>" + stu.getSname() + "</td>");
w.print("<td>" + stu.getSex() + "</td>");
w.print("<td>" + stu.getHobby() + "</td>");
w.print("<td>" + stu.getSchool() + "</td>");
w.print("</tr>");
}
w.print("</table>");
}
}
1. request.getServletContext();
2. this.getServletContext();
package com.ujiuye.servlet;
import com.ujiuye.bean.Student;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* 获取ServletContext 和域对象
*/
@WebServlet("/demo05")
public class Demo05Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
//获取 servletContext在web应用是唯一的
/*ServletContext sc1 = getServletContext();
ServletContext sc2 = this.getServletContext();
System.out.println(sc1 == sc2);//true*/
/**
* ServletContext和request都是域对象
* 什么是域对象 可以向对象中存值取值的对象,并且拥有作用域范围
* 1、域对象如何存值、取值、移除值
* 存 setAttribute(string,object)
* 取 getAttribute(key)
* 移除 removeAttribute(key)
* 2、ServletContext和request存取移除值的方式都是一样的
* 3、作用域范围
* ServletContext是整个web应用
* request作用域范围是一次请求
* 4、获取文件的真实路径 获取的是工件在本地的真实路径
* getRealPath
*/
ServletContext sc = getServletContext();
//存值
Student s = new Student();
s.setSname("张三");
sc.setAttribute("student",s);
//取值 通过key获取value
Student student = (Student) sc.getAttribute("student");
System.out.println("student = " + student);
//移除值
sc.removeAttribute("student");
System.out.println(sc.getAttribute("student"));
String realPath = sc.getRealPath("/");
System.out.println("realPath = " + realPath);
}
}
ServletContext作用域:
1、在Demo06Servlet中存值
package com.ujiuye.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 测试ServletContext和request的作用范围
*/
@WebServlet("/demo06")
public class Demo06Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
//设置请求和响应的字符集
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
ServletContext sc = getServletContext();
sc.setAttribute("name","张三");
req.setAttribute("age",17);
}
}
2、 在Demo07Servlet中取值
package com.ujiuye.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 测试ServletContext和request的作用范围
*/
@WebServlet("/demo07")
public class Demo07Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
//设置请求和响应的字符集
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//获取servletContext中的值
ServletContext sc = getServletContext();
Object name = sc.getAttribute("name");
System.out.println("name = " + name);
Object age = req.getAttribute("age");
System.out.println("age = " + age);
}
}
总结:
request作用域仅限于一次请求范围内可以实现信息的共享,一次请求结束,request对象消失, 内部的值也随之消失,周期短,但效率高,不会占用过多的内存资源;而ServletContext是一个全局 作用域对象,整个web项目的所有组件(Servlet、jsp)共享信息,周期长,可用来保存所有web组件之 间需要共享的信息。它在tomcat服务器启动时创建,关闭时销毁。
2.获取文件的真实路径
获取文件的真实路径方法:
getRealPath("web下的资源路径");
无论是转发还是重定向都起到了跳转页面、跳转到其他地址的作用
转发 req.getRequestDispatcher("success.html").forward(req, resp);
案例:在AServlet中向request作用域中保存信息并以转发的方式跳转到BServlet
结论: bServlet可以获取到request作用域的值
案例实现:
Aservlet:
package com.ujiuye.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
//向request作用域中存值
req.setAttribute("sex","nan");
//转发到bServlet
req.getRequestDispatcher("bServlet").forward(req,resp);
//重定向到bServlet
//resp.sendRedirect("bServlet");
}
}
Bservlet:
package com.ujiuye.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/bServlet")
public class BServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//获取request作用域的值
Object sex = req.getAttribute("sex");
System.out.println("sex = " + sex);
}
}
package com.ujiuye.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
//向request作用域中存值
req.setAttribute("sex","nan");
//转发到bServlet
//req.getRequestDispatcher("bServlet").forward(req,resp);
//重定向到bServlet
resp.sendRedirect("bServlet");
}
}
BServlet:
package com.ujiuye.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/bServlet")
public class BServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//获取request作用域的值
Object sex = req.getAttribute("sex");
System.out.println("sex = " + sex);
}
}
一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su
TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是
开门见山|拉取镜像dockerpullelasticsearch:7.16.1|配置存放的目录#存放配置文件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/config#存放数据的文件夹mkdir-p/opt/docker/elasticsearch/node-1/data#存放运行日志的文件夹mkdir-p/opt/docker/elasticsearch/node-1/log#存放IK分词插件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/plugins若你使用了moba,直接右键新建即可如上图所示依次类推创建
文章目录概念索引相关操作创建索引更新副本查看索引删除索引索引的打开与关闭收缩索引索引别名查询索引别名文档相关操作新建文档查询文档更新文档删除文档映射相关操作查询文档映射创建静态映射创建索引并添加映射概念es中有三个概念要清楚,分别为索引、映射和文档(不用死记硬背,大概有个印象就可以)索引可理解为MySQL数据库;映射可理解为MySQL的表结构;文档可理解为MySQL表中的每行数据静态映射和动态映射上面已经介绍了,映射可理解为MySQL的表结构,在MySQL中,向表中插入数据是需要先创建表结构的;但在es中不必这样,可以直接插入文档,es可以根据插入的文档(数据),动态的创建映射(表结构),这就
HTTP缓存是指浏览器或者代理服务器将已经请求过的资源保存到本地,以便下次请求时能够直接从缓存中获取资源,从而减少网络请求次数,提高网页的加载速度和用户体验。缓存分为强缓存和协商缓存两种模式。一.强缓存强缓存是指浏览器直接从本地缓存中获取资源,而不需要向web服务器发出网络请求。这是因为浏览器在第一次请求资源时,服务器会在响应头中添加相关缓存的响应头,以表明该资源的缓存策略。常见的强缓存响应头如下所述:Cache-ControlCache-Control响应头是用于控制强制缓存和协商缓存的缓存策略。该响应头中的指令如下:max-age:指定该资源在本地缓存的最长有效时间,以秒为单位。例如:Ca
如何用IDEA2022创建并初始化一个SpringBoot项目?目录如何用IDEA2022创建并初始化一个SpringBoot项目?0. 环境说明1. 创建SpringBoot项目 2.编写初始化代码0. 环境说明IDEA2022.3.1JDK1.8SpringBoot1. 创建SpringBoot项目 打开IDEA,选择NewProject创建项目。 填写项目名称、项目构建方式、jdk版本,按需要修改项目文件路径等信息。 选择springboot版本以及需要的包,此处只选择了springweb。 此处需特别注意,若你使用的是jdk1
前言上一篇我们简要讲述了粒子系统是什么,如何添加,以及基本模块的介绍,以及对于曲线和颜色编辑器的讲解。从本篇开始,我们将按照模块结构讲解下去,本篇主要讲粒子系统的主模块,该模块主要是控制粒子的初始状态和全局属性的,以下是关于该模块的介绍,请大家指正。目录前言本系列提要一、粒子系统主模块1.阅读前注意事项2.参考图3.参数讲解DurationLoopingPrewarmStartDelayStartLifetimeStartSpeed3DStartSizeStartSize3DStartRotationStartRotationFlipRotationStartColorGravityModif
VMware虚拟机与本地主机进行磁盘共享前提虚拟机版本为Windows10(专业版,不是可能有问题)本地主机为家庭版或学生版(此版本会有问题,但有替代方式)最好是专业版VMware操作1.关闭防火墙,全部关闭。2.打开电脑属性3.点击共享-》高级共享-》权限4.如果没有everyone,就添加权限选择完全控制,然后应用确定。5.打开cmd输入lusrmgr.msc(只有专业版可以打开)如果不是专业版,可以跳过这一步。点击用户-》administrator密码要复杂密码,否则不行。推荐admaiN@1234类型的密码。设置完密码,点击属性,将禁用解开。6.如果虚拟机的windows不是专业版,可
IK分词器本文分为简介、安装、使用三个角度进行讲解。简介倒排索引众所周知,ES是一个及其强大的搜索引擎,那么它为什么搜索效率极高呢,当然和他的存储方式脱离不了关系,ES采取的是倒排索引,就是反向索引;常见索引结构几乎都是通过key找value,例如Map;倒排索引的优势就是有效利用Value,将多个含有相同Value的值存储至同一位置。分词器为了配合倒排索引,分词器也就诞生了,只有合理的利用Value,才会让倒排索引更加高效,如果一整个Value不进行任何操作直接进行存储,那么Value和key毫无区别。分词器Analyzer通常会对Value进行操作:一、字符过滤,过滤掉html标签;二、分
题外话:抑郁场,开局一小时只出A,死活想不来B,最后因为D题出锅ura才保住可怜的分。但咱本来就写不到DB-LongLegs(数论)本题题解法一学自同样抑郁的知乎作者幽血魅影的题解,有讲解原理。法二来着知乎巨佬cup-pyy(大佬说《不难发现》呜呜)题意三种操作:向上走mmm步向右走mmm步给自己一次走的步数加111,即使得m=m+1m=m+1m=m+1问从(0,0)(0,0)(0,0)走到(a,b)(a,b)(a,b)的最小操作次数,值得注意的是操作三不可逆。解析假设我们最终一步的大小增长到mmm,那么在这个过程中我能以[1,m][1,m][1,m](当步数增长到该数时)之间的任何数字向上或