06 Servlet
Servlet与jsp是等价的。
1、Servlet是JavaEE规范之一。规范就是接口
2、Servlet就JavaWeb三大组件之一。三大组件分别是:Servlet程序、Filter过滤器、Listener监听器。
3、Servlet是运行在服务器上的一个java小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。
Servlet可以连接java代码与前端代码Html之间,架成桥梁传输数据。jsp就是HTML与java代码的整合,既可以写后端代码也可以写前端代码所以并没有实现前后端分离,但是前后端分离的基础。
后面通过规定消息转发,就是json数据传输格式实现前后端分离。
等价于jsp作用类似。
获取协议信息 修改协议信息
获取标签信息 修改标签信息
遵循HTTP协议,继承HttpServlet类
在这个继承类中写http页面信息。会初始化一些协议信息,并构建http页面内容。
提供将要被子类化以创建适用于 Web 站点的 HTTP servlet 的抽象类。HttpServlet
的子类至少必须重写一个方法,该方法通常是以下这些方法之一:
doGet
,如果 servlet 支持 HTTP GET 请求doPost
,用于 HTTP POST 请求doPut
,用于 HTTP PUT 请求doDelete
,用于 HTTP DELETE 请求init
和destroy
,用于管理 servlet 的生命周期内保存的资源getServletInfo
,servlet 使用它提供有关其自身的信息
-
简述HTTP协议的概念及特点
-
支持客户/服务器模式。
-
简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有 GET、POST。每种方法规定了客户与服务器联系的类型不同。由于 HTTP 协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
-
灵活:HTTP 允许传输任意类型的数据对象。传输的类型由Content-Type加以标记。
-
无连接:无连接是表示每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
HTTP1.1 版本后支持可持续连接。通过这种连接,就有可能在建立一个 TCP 连接后,发送请求并得到回应,然后发送更多的请求并得到更多的回应.通过把建立和释放 TCP 连接的开销分摊到多个请求上,则对于每个请求而言,由于 TCP 而造成的相对开销被大大地降低了。而且,还可以发送流水线请求,也就是说在发送请求 1 之后的回应到来之前就可以发送请求 2.也可以认为,一次连接发送多个请求,由客户机确认是否关闭连接,而服务器会认为这些请求分别来自不同的客户端。
-
无状态:HTTP 协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快
-
-
简述实现Servlet的步骤
创建Servlet
- 创建普通 java类
- 遵循servlet标准(继承 HttpServlet)
- 重写service方法(当前Servlet 类被访问时自动调用service方法)
- 设置对外访问的路径 (设置@WebServlet("/路径"))
-
简述Servlet的生命周期
- init()初始化在被调用的时候创建。
- serivce()处理客服的请求方法。
- destroy()服务关闭时调用。
-
简述Servlet的请求过程
转载:https://blog.csdn.net/qq_19782019
第一次请求:
①.解析请求信息,解析/one/hello;
上下文路径(环境):/one.
资源名称:/hello.
②.根据上下文路径/one去Tomcat根/conf下找到server.xml文件获取所有的元素再判断哪一个元素的path属性值为/one,接着找到的docBase属性值,该属性值就是当前访问项目的根路径.
③.再从当前项目的根路径下的WEB-INF目录中识别web.xml文件.
④.获取web.xml文件中所有的url-pattern元素,判断是否存在/hello的属性值(找不到则报404错误).
⑤.根据/hello资源名称最终获取对应的Servlet类的全限定名(类的包名.类名).
⑥.根据Servlet的全限定名,使用反射调用构造器创建对象Servlet obj = Class.forName(Servlet全限定名).
(把创建的Servlet对象存储到Servlet缓存池中,供下一次请求使用)
⑦.容器创建ServletConfig对象再使用Servlet对象调用init方法进行初始化 obj.init(config).
⑧.容器创建ServletRequest,ServletResponse对象再使用Servlet对象调用service方法进行服务obj.service(req, resp).
⑨.在service方法中对客户端做响应操作.
非第一次请求
前五步与上述前五步相同.
⑥.从Tomcat中的Servlet实例缓存池中取出HelloServlet对象
⑦.创建HttpRequest,HttpResponse对象调用Service方法进行服务 obj.service(req, resp).
⑧.在service方法中对客户端做响应.
上述流程均有Tomcat容器完成,Servlet,ServletConfig,HttpRequest,HttpResp对象均由容器创建.
Servlet中方法调用先后顺序:init---->service---->destroy运行时如下图所示:
-
简述GET请求和POST请求的区别?
-
get请求提交的数据会在地址栏显示出来,而post请求不会在地址栏显示。
get请求,请求的数据会附在url之后(就是把数据放置在http协议头中),以?分割url协议和传输数据,多个参数用&连接
post请求,把请求的数据放在http包的包体中。
因此,get请求的数据会在地址栏中显示出来,而post请求地址栏不会改变。 -
传输数据的大小
get请求由于浏览器对地址url长度的限制而导致传输数据有限制
post请求不会因为地址长度限制而导致传输数据限制 -
安全性,post的安全性比get的安全性要高
-
-
如何获取请求的数据?如何响应数据给客户端?
获取请求数据request:
HttpServletRequest 对象用于获取客户端发送给服务器的请求数据;
核心 API:
获取请求行数据:
request.getMethod():获取请求方式;
request.getRequestURI():获取请求资源;
request.getProtocal():获取请求的 http 协议版本;
获取请求头数据:
request.getHeader(“名称”):根据请求头名称获取对应的值;
request.getHeaderNames():获取所有的请求头名称;
获取实体内容:
request.getInputStream():获取实体内容数据;
获取请求参数:
request.getParameter(“参数名”):根据参数名获取参数值(注意,只能获取一个参数的值)
request.getParameterValue(“参数名”):根据参数名获取参数值(可以获取多个值的参数)
request.getParameterNames():获取所有参数名称列表响应数据给客服端response:
- 设置响应头信息; addHeader(ket,value) setHeader(key,value) set键名(value)
- response.addHeader(“a”,“A”);response.addHeader(“Content-type”,“text/html;charset=utf-8”);
- response.setHeader(“Refresh”,“5;URL=www.baidu.com”);5秒后自动跳转到百度主页
- 发送状态码;
- response.setStatus(int code);
- response.sendError(int code , String msg);
- 设置响应正文;
- PrintWriter out = response.getWriter();//获取字符流
- ServletOutputStream out = response.getOutputStream();//获取字节流
- 重定向;
- response.setHeader(“Location”, “/day05/index.jsp”);
- response.sendRedirect("/day05/index.jsp");
- 设置响应头信息; addHeader(ket,value) setHeader(key,value) set键名(value)
-
如何处理乱码问题(请求与响应)
编码与解码统一 所以在写入与显示设置编码格式
请求乱码
在请求头中有页面显示的编码格式:
下图是百度搜索,所以他接受的信息是文本与图片text/plain
设置请求头中Content-Type的键值为:charset=UTF-8
request.setHeader(“Content-Type”,“text/html;charset=utf-8”);
request.setCharacterEncoding(“UTF-8”);
响应乱码
response.setCharacterEncoding(“UTF-8”);
response.setHeader(“content-type”,“text/html;charset=utf-8”);
写入也需要注意,若idea默认是"UTF-8"则无需修改,否则需要在写入字符串后面填写写入的编码格式。
ServletOutputStream outputStream = response.getOutputStream(); outputStream.write("你好".getBytes()); outputStream.write("<h2>hello<h2>".getBytes("UTF-8")); outputStream.flush();
-
request.getAttribute()和request.getParameter()的区别?
- getAttribute表示从request范围取得设置的属性,必须要先setAttribute设置属性,才能通过getAttribute来取得,设置与取得的为Object对象类型
- getParameter表示接收参数,参数为页面提交的参数,包括:表单提交的参数、URL重写(就是xxx?id=1中的id)传的参数等,因此这个并没有设置参数的方法(没有setParameter),而且接收参数返回的不是Object,而是String类型
-
请求转发forward和重定向redirect的区别?
forward(转发):
是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,因为这个跳转过程实在服务器实现的,并不是在客户端实现的所以客户端并不知道这个跳转动作,所以它的地址栏还是原来的地址.
redirect(重定向):
是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.
转发是服务器行为,重定向是客户端行为。
区别:
- 从地址栏显示来说
forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.
redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.
-
从数据共享来说
forward:转发页面和转发到的页面可以共享request里面的数据.
redirect:不能共享数据. -
从运用地方来说
forward:一般用于用户登陆的时候,根据角色转发到相应的模块.
redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等 -
从效率来说
forward:高.
redirect:低.
本质区别:
重定向,其实是两次request,请求转发是一次request。
转发是服务器行为,重定向是客户端行为。
- 从地址栏显示来说
Filter过滤器
在服务器一启动就创建,并每个接口都要先经过filter过滤器,判断是否要过滤,从而在执行。过滤器执行的先后顺序是根据过滤器的名字排序的。一层一层判断。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hBWVIUSa-1605619461625)(javaweb.assets/image-20201117210523710.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W1mwFwib-1605619461626)(javaweb.assets/image-20201117210823920.png)]
@WebFilter("/*")
public class Filter01 implements Filter {
//初始拦截器 项目启动时
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
//拦截后的处理
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//1. 可设置请求与及相应的编码格式
HttpServletRequest request= (HttpServletRequest) servletRequest;
HttpServletResponse response= (HttpServletResponse) servletResponse;
request.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "text/html; charset=UTF-8");
//2.连接资源文件的请求 或所需拦截的要求 登录以及必须填写某项记录
if(true){
//拦截前操作
System.out.println("拦截前操作");
//放行
filterChain.doFilter(request, servletResponse);
//放行后操作
System.out.println("放行后操作");
}else {
System.out.println("拦截");
}
}
//拦截器销毁 项目关闭时
@Override
public void destroy() {
}
}