servlet
Servlet 介绍
Servlet规范是SUN公司定义一套规则
作用:
动态资源文件开发规则
Http服务器应该如何调用管理动态资源文件
Servlet规范定义了规则关联的接口,实现类有Http服务器厂商提供
Tomcat中对于Servlet规范中接口实现存放servlet-api.jarweb服务器
用于提供相关的服务组件运行的环境。
以及解决用户并发访问和处理业务逻辑的软件。
TomCat
:apache组织开源的一个服务器。
使用版本:apache-tomcat-9.0.30
Jboos
:处理并发量很大,功能很健全的一个商用服务器。
webLojec
:与Jboos相同组件
符合规范,实现部分功能,并且需要部署到相应的服务器中才能运行的软件模块。
servlet就是一个符合规范的组件,需要部署才能运行。
1 | Servlet请求-响应的过程 |
Servlet接口实现类开发规则
基于servlet_2.0规范 通过配置文件通知Tomcat哪一个类是Servlet接口实现类
1)创建Servlet接口实现类 继承 HttpServlet
2)重写父类(HttpServlet)中(service)方法
3)web.xml基于servlet_3.0规范 通过注解通知TomcatTomcat哪一个类是Servlet接口实现类(推荐)
如何执行
大致流程
- 浏览器会依据ip:端口号来【建立连接】
- 浏览器会将请求数据打包
- 发送请求数据包
- 服务器接收请求
- 服务器解析请求数据包
- 创建request 和 response对象
- 创建servlet对象
- 调用service方法,依据请求方式的不同在分别调用doGet 和 doPost方法
- 处理业务逻辑
- 将处理完的数据放入response对象中
- 服务器引擎从response对象中获取数据。
- 服务器引擎将响应数据打包
- 发送响应给请求的浏览器
- 浏览器接收响应数据包并解析数据渲染画面给用户。
- 断开连接
1 | import javax.servlet.ServletException; |
web.xml
1 | <!-- 欢迎页 --> |
获取请求参数
前台提供name属性。name属性是在浏览器打包时,会将name作为key 用户输入的值作为value
后台需要使用key才能获取value
前台:form表单中的属性:
action:服务器提交地址,比如(“test”)
method:get【默认】或者 post
后台:调用
req.getParameter(String key)
req.getParameterValues(String key);
- 看代码
1
2
3
4
5
6
7
8
9
10
11//调用请求对象读取请求行中参数
String deptNo = request.getParameter("deptNo");
String dname = request.getParameter("dname");
String array[] = request.getParameterValues("ck");
for(String value:array){
System.out.println("ck = "+value);
}
System.out.println("deptNo = "+deptNo);
System.out.println("dname = "+dname);1
2
3
4
5
6
7
8<form action="/myWeb/four">
部门编号:<input type="text" name="deptNo"><br/>
部门名称:<input type="text" name="dname"><br/>
部门业务:<input type="checkbox" name="ck" value="java">java
<input type="checkbox" name="ck" value="mysql">mysql
<input type="checkbox" name="ck" value="html">html<br/>
<input type="submit" value="访问FourServlet">
</form>
请求方式
get请求
- 哪些情况下使用get请求。
在点击某个链接时,使用get请求
表单的默认提交方式。 - 特点:
不安全,会将请求参数值显示在浏览器地址连中
请求数据有限,最大2K左右
- 哪些情况下使用get请求。
post请求
- 哪些情况下使用post请求
表单提交时一般使用post请求方式
Ajax请求时一般使用post请求 - 特点;
安全,将请求数据放在from data 中
相对请求数据会大一些
- 哪些情况下使用post请求
jsp
java server page【java 服务端网页】
也是一个标准的web组件,用来解决使用servlet编写网页的繁琐。
其本质就是一个servlet。但是它是以.jsp结尾的一个开源编写HTML、CSS、JS、JAVA代码的文件。
JSP在执行的时候,会被JSP引擎加载,将其中的Java代码转换成.java文件 照搬到其中
HTML采用out.writer()的方式输出,变量采用out.print()输出。
1 | JSP文件运行原理:(面试常考问题) |
通俗的理解
:.jsp文件会被转换成.java文件 最终执行的是.class文件。
语法:
1 | <% |
处理请求资源路径 @WebServlet
匹配规则:
- 精确匹配
要求:@WebServlet(value = “/delete”)中的value值必须一致。【value可以省略】 - 通配符匹配
要求:使用 * 代替 ,代表任意字符串
比如:/abc/* - 后缀匹配
要求:不能以 “/“ 开头,要求 .任意字符
比如:.do 或 *.action *.com
处理多种请求
String path = request.getRequestURI();
String path = uri.substring(uri.lastIndexOf("/") + 1,uri.lastIndexOf("."));
例子:
1 | // 只要输入xxx.com的都进入到这个文件 |
重定向
1.什么是重定向?
服务器向浏览器响应的时候,会在响应数据包中,添加一个状态码。302状态码,当浏览器解析响应数据包时,如果解析到302状态码,浏览器会立即向302状态所指向的url地址重新发送一个新的请求。
2.如何进行重定向response.sendRedirect(String url);
3.重定向的特点
重定向的地址是任意的
转发
什么是转发?
转发就是一个web组件将一件没有完成的任务
转交给另一个web组件继续完成的过程。
通俗的理解:一个任务多个组件协同完成。
转发是各个组件可以共享数据以及 request 和response对象
转发的特点
1.转发后浏览器地址栏地址不变。因为转发是服务器内部的,浏览器无感知
2.转发必须共享request和response对象
3.转发必须先绑定后获取
如何转发
1 | // 1. 先将处理好的数据绑定到request对象中 |
状态管理 Cookie & Session
什么是状态管理?
将浏览器与web服务器之间多次交互当做是一个整体来处理,
并且将多次交互产生的数据【状态】保存下来。
比如:验证码Cookie类
将状态保存在浏览器端浏览器在访问服务器时,服务器会将一些数据以 set-cookie 消息头的形式发送给浏览器。
浏览器将这些数据保存起来。当浏览器在次访问服务器时,会将这些数据以cookie消息头的
形式,发送给服务器,通过这种方式来保存用户状态。可以理解为,服务器临时保存在浏览器端的少量数据。
设置cookie的路径
浏览器在向服务器发送cookie的时候,会先比较cookie的路径与请求的路径是否匹配,如果匹配会将匹配的cookie发送到服务器,否则不发送
比如:
创建cookie保存的路径是,/day04_war_exploded/cookie
1.访问cookie的路径如果是:/day04_war_exploded/cookie/findCookie.jsp能访问到
2.访问cookie的路径如果是:/day04_war_exploded/findCookie.jsp访问不到
3.访问cookie的路径如果是:/day04_war_exploded/cookie/cookie2/findCookie.jsp能访问到
结论:
只要是创建路径下的子路径都可以访问。方法:
request.setPath(String path):设置cookie的路径
request.getContextPath():获取 Application Context【】
例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/*
创建cookie并发送到浏览器端
*/
public class CreateCookie extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建cookie
Cookie cookie = new Cookie("isdn", UUID.randomUUID().toString());
//设置cookie的生命周期
cookie.setMaxAge(60);//秒
//发送cookie
response.addCookie(cookie);
}
}HttpSession接口
将状态保存在服务器端浏览器访问服务器时,服务器会创建一个session对象,session对象中保存一个唯一的ID 称为JSESSIONID,服务器会将JSESSIONID以cookie的形式,发送给浏览器端,浏览器进行保存。
当浏览器第二次访问服务器时,浏览器将JSESSIONID再次发送给服务器,服务器依据JSESSIONID查找对应的session对象,如果找到,则使用,否则创建一个新的session对象。总结:
session对象的创建是服务器创建的方法:
HttpSession session = request.getSession():获取服务器创建的session对象。
session.setAttribute(Object key,Object value):绑定数据到session中
Object obj = session.getAttribute(Object key):根据key获取value
例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16/*
session对象获取绑定数据
*/
public class SessionObject extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取服务器创建的session对象
HttpSession session = request.getSession();
System.out.println(session.getId());
//将数据绑定到session对象中
session.setAttribute("checkcode","123456");
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23/*
验证验证码是否正确
*/
public class CheckCodeServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取服务器创建的session对象
HttpSession session = request.getSession();
System.out.println(session.getId());
//获取
String code = (String) session.getAttribute("checkcode");
//从前台获取name来判断是否相等
String checkcode = request.getParameter("checkcode");
if (code.equals(checkcode)) {
System.out.println("验证码正确");
} else {
System.out.println("验证码错误");
}
}
}注意:
request也有setAttribute
session也有setAttribute
存在的区别是生命周期的长短
reuqest:请求到响应-死亡
session:浏览器关闭、session超时、服务器关闭
ServletContext
- 概念
web 服务器在启动时,会为每一个工程都创建一个唯一的 ServletContext 对象。
该实例会一直存在,除非服务器宕机,或者关机。(生命周期长)
获取ServletContext实例
1 | //方式一 |
如何使用ServletContext实例?
1.绑定数据
2.获取绑定数据
1.配置全局初始化参数【了解】
2.获取全局初始化参数
绑定且获取数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import 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;
public class Test extends HttpServlet {
public Test() {
System.out.println("无参构造器运行。。。");
}
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取ServletContext实例
ServletContext servletContext = this.getServletContext();
//绑定数据
servletContext.setAttribute("name", "葫芦啊葫芦");
}
}1
2
3
4
5
6
7
8<body>
<!-- 获取数据 -->
<%
Object name = application.getAttribute("name");
%>
<!-- 输出“葫芦啊葫芦” -->
<h1><%=name%></h1>
</body>配置全局初始化参数 且 获取全局初始化参数
1
2
3
4<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://127.0.0.1:3306/gz2107?useUnicode=true&characterEncoding=utf8</param-value>
</context-param>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Test extends HttpServlet {
public Test() {
System.out.println("无参构造器运行。。。");
}
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
//获取初始化参数
String url = servletContext.getInitParameter("url");
System.out.println(url);
// 最后输出 jdbc:mysql://127.0.0.1:3306/gz2107?useUnicode=true&characterEncoding=utf8
}
}
生命周期
概念
Servlet 容器如何创建 Servlet 实例,分配其资源,调用其方法,并且销毁其 实例 的整个过程。阶段一:
实例化【创建servlet对象,调用其构造器】
1.当请求到达容器时,容器会查找该servlet实例是否存在,如果不存在,则创建新的实例。
2.容器在启动的时候,会查找每个Servlet中是否配置了loadOnStartUp配置,如果有,会立即创建该servlet的实例。
loadOnStartup
的值越小优先级越高。最高10阶段二:
初始化
为servlet分配资源,调用init(ServletConfig config)方法
config 对象可以访问到servlet的初始化参数。
ServletConfig:servlet对象一旦创建会自动调用init
方法获取初始化参数。
- 阶段三:
就绪/调用
容器调用servlet实例的service方法根据请求类型的不同
来分别调用不同请求类型所对应的方法。
- 阶段四:
销毁
容器依据自身算法,将不再使用的servlet实例删除掉
在删除之前会调用servlet实例的destroy
方法来释放资源。
注意:init方法和destroy方法只会执行一次,而service方法每一个请求都会执行。
1 |
|
监听器 @WebListener
- 什么是监听器?
监视容器中的各种对象的事件。它是一个特殊的接口
一般与servlet的生命周期相关。
- 如何写一个监听器
写一个java类实现特定监听器的接口【依据要监听的事件类型】
在接口中实现回到方法。
配置监听器
例子:
1 | // 监听一 |
过滤器 @WebFilter
- 概念
请求到达servlet之前,会对请求进行拦截,过滤、筛查到达Servlet实例的请求是否符合标准。(请求时先到达过滤器。)
写一个过滤器
实现Filter接口,并实现其doFilter方法。配置Filter访问路径。
doFilter方法:
参数介绍:
ServletRequest 是 HttpServletRequest的父类
ServletResponse 是 HttpServletResponse的父类
FilterChain:过滤器链
过滤器链有一个方法:doFilter(request,response);
//调用后续过滤器,如果没有过滤器则调用servlet
例子:过滤敏感字
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> |
1 | import javax.servlet.*; |
跨域 与 同源 请求
浏览器的同源策略:
是浏览器最核心也是最基本的安全功能。出于安全考虑 如果请求的域名、协议、端口有一个不同就不是同源,三者均相同,这两个网站才是同源。
跨域请求:
这里的域指的是这样的一个概念:我们认为如果 “协议 + 域名 + 端口号” 均相同,那么就是同域。
当前发起请求的域与该请求指向的资源所在的域不一样。
解决跨域请求:过滤器添加这三条
1 | res.setHeader("Access-Control-Allow-Origin", "*"); |
JSTL
英文:java stander taglib
是java 标准标签库,使用需要导jar包
是用来将jsp页面中的java代码采用类似于html标签的形式来输出的一种技术。
看代码
1 | 1.如何使用JSTL? |
EL表达式
Expression language 表达式语言
是一种可以在JSP页面获取数据的一种方式。
完整语法:${作用域对象别名.共享数据名.属性名}
简写语法:${共享数据名}
执行原理:
依次查找pageContext、request、session、application
所绑定的key,
如果查找到,则调用key所绑定的value值的getXXX方法来获取数据。作用域
requestScope
:只在request作用域中查找指定的绑定名
sessionScope
:只在session作用域中查找指定的绑定名
applicationScope
:只在servletContext作用域中查找指定的绑定名注意:
el表达式只能获取数据,不能设置数据。
el表达式可以进行计算,可以调用方法。
el表达式不能进行字符串的拼接支持运算
大于 大于等于 等于 小于 小于等于 不等于 gt ge eq lt le != > >= = < <= != 时间格式化
1
<formatDate value="${你的时间对象}" pattern="yyyy-MM-dd" />
json
把java对象转换成json对象传给前台
需要导入jar包,(这里我选择jackson)
例子:
1 | ObjectMapper om = new ObjectMapper(); //新建对象 |