Servlet基础知识
S ervlet概念
Servlet(server applet)概念:运行在服务器端的小程序
之前讲解HTML的时候提到过动态资源技术有Servlet,动态资源可以让两个用户请求同一个服务器时获得不同的响应,说明在Servlet中存在代码逻辑,而Java中所有的代码都是被封装到类中的,所以访问一台服务器上的Servlet其实就是在访问这个Servlet中的那个Java类
Servlet中的Java类非常特殊,这个类没有主方法,也就是说没有程序运行的入口,这个类直接依赖服务器
但是并不是所有的Java类都是可以被当前主机或者其他主机通过浏览器的方式访问,需要给实现处理用户请求的Java类定义一个规则,这个规则就是一个接口,这个接口名字也叫Servlet,遵守这个规则才能被Tomcat识别
所有实现Servlet接口的类都可以叫做Servlet(运行在服务器端的小程序)
在Java EE的API文档中查看Servlet接口中定义的方法
可以看到该接口中的5个方法
Servlet代码示例
在了解了Servlet的概念后我们通过一个简单的项目来演示Servlet接口的用法
Servlet的创建步骤
创建JavaEE项目
定义一个类,实现Servlet接口
extends HttpServlet
public class servlet extends HttpServlet {
public servlet() {
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入doGet");
PrintWriter writer = resp.getWriter();
writer.println("hello servlet");
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
实现接口中的抽象方法
配置Servlet
在web.xml中配置:
<servlet>
<servlet-name>别称</servlet-name>
<servlet-class>实现Servlet接口的类的路径</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>别称</servlet-name>
<url-pattern>虚拟路径</url-pattern>
</servlet-mapping>
配置Servlet
在web.xml中配置
Servlet执行原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IniuY4SP-1620309139041)(Servlet.assets/image-20210418215812761.png)]
seveletConyext
从servletConyext中取值
public class GetServletContext extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String name = (String) servletContext.getAttribute("name");
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
resp.getWriter().println("名字"+name);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
赋值到servletContext
public class Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入doGet");
PrintWriter writer = resp.getWriter();
writer.println("hello servlet");
ServletContext servletContext = this.getServletContext();
String name = "张三";
servletContext.setAttribute("name",name);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
HttpServletResponse
下载
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bp7Q790A-1620309139044)(Servlet.assets/image-20210419145311446.png)]
下载文件
public class Response extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取要下载的文件路径
String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/23.jpg");
System.out.println("下载文件的路径"+realPath);
//2.下载的文件名是啥
String filename = realPath.substring(realPath.lastIndexOf("\\")+1);
//3.设置想办法让浏览器能够支持下载我们需要的东西
System.out.println("下载的文件名"+ filename);
resp.setHeader("Content-disposition","attachment;filename"+filename);
//4.获取下载的文件输入流
FileInputStream fileInputStream = new FileInputStream(realPath);
//5.创建缓冲区
int len = 0;
byte[] buffer = new byte[1024];
//6.获取OutputStream对象
ServletOutputStream outputStream = resp.getOutputStream();
//7.将FileOutputStream流写入buffer缓冲区中 使用OutputStream将缓冲区的数据输出到客户端
while ((len = fileInputStream.read(buffer))>0 ){
outputStream.write(buffer,0,len);
}
//8.关闭
fileInputStream.close();
outputStream.close();
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
重定向(sendRedirect)
resp.sendRedirect("");
重定向和转发的区别
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HfgqYUnz-1620309139045)(Servlet.assets/image-20210419164226156.png)]
表单提交
<html >
<head>
</head>
<body>
<form action="/Response/t" method="post">
<span>用户</span><input name="username"><br>
<span>密码</span><input name="password"><br>
<span>登录</span><input type="submit">
</form>
</body>
</html>
java代码
public class ResponseText extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入这个请求");
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+":"+password);
resp.sendRedirect("/Response/success.html");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
根据设置的虚拟路径找到对应的项目
查找项目中的web.xml文件,是否有对应的标签体内容。
如果有,则在找到对应的全类名
tomcat会将字节码文件加载进内存,并且创建其对象,这就涉及到之前讲解的反射的知识
调用其方法
Servlet中的生命周期方法
被创建:执行init方法,只执行一次
Servlet什么时候被创建?
默认情况下,第一次被访问时,Servlet被创建
可以配置执行Servlet的创建时机。在标签下配置
第一次被访问时,创建, 的值为负数
在服务器启动时,创建,的值为0或正整数
上述Servlet的init值执行一次,说明我们编写的类在计算机中只存在一个对象
因为只存在一个对象,多个用户同时访问时,可能存在线程安全问题。应该尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对修改值
提供服务:执行service方法,执行多次
每次访问Servlet时,Service方法都会被调用一次。
被销毁:执行destroy方法,只执行一次
Servlet被销毁时执行。服务器关闭时,Servlet被销毁, 只有服务器正常关闭时,才会执行destroy方法。 destroy方法在Servlet被销毁之前执行,一般用于释放资源
注解开发
使用注解开发Servlet不需要再使用web.xml文件了,可以直接使用注解来配置每个实现Servlet接口的类的访问路径
将之前在web.xml中定义的一些标签全部删除
在ServletDemo1中进行相应的修改
package com.westos.web.servlet;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet("/demo1")
public class ServletDemo1 implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("你好servlet");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
erride
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println(“你好servlet”);
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}