Servlet入门

环境

在IDEA中创建JavaEE项目

项目运行后,会显示webapp中的index.htmlindex.jsp中的内容,

调试

  • 用Lombok里的@Log,或者System.out.println()

0、JavaEE项目运行

两种方法:

  1. 直接运行项目
  2. 将项目打包,生成一个war包,之后在Tomcat中运行

下面是第二种方法:

运行startup.bat,启动Tomcat


Tomcat中有默认的servlet-mapping,所以我们才能看到Tomcat 的页面

1、创建Servlet

Servlet是一个标准,web服务器Tomcat支持此标准。官方定义接口,程序员实现,之后Web服务器(Tomcat)运行这些实现。

用注解注册一个Servlet

java 复制代码
@WebServlet("/test")
public class TestServlet implements Servlet {

    public TestServlet(){
        System.out.println("我是构造方法!");
    }


    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init");
    }

    @Override
    public ServletConfig getServletConfig() {
        System.out.println("我是getServletConfig");
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("我是service");
    }

    @Override
    public String getServletInfo() {
        System.out.println("我是getServletInfo");
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("我是destroy");
    }
}

web.xml中注册Servlet【一般不用】

xml 复制代码
<!--    Servlet,对应的是哪个文件-->
<servlet>
    <servlet-name>test</servlet-name>
    <servlet-class>com.example.webtest.TestServlet</servlet-class>
</servlet>
<!--    映射(通过哪个路径访问)-->
<servlet-mapping>
    <servlet-name>test</servlet-name>
    <url-pattern>/test</url-pattern>
</servlet-mapping>

2、Servlet的生命周期

问题:Servlet启动/关闭时,哪些方法被执行了?

复制代码
答:
请求url时,初始化Servlet(构造方法,init)
调用Service处理客户端请求
//中间的多次请求,只调用Service
销毁前调用destroy方法
最后用JVM的垃圾回收器,进行回收


3、Servlet的Service方法

java 复制代码
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    System.out.println("我是service");
}

参数:

  • servletRequest:客户端发送的HTTP请求,被接收到这里(可从这获取所有请求信息)
  • servletResponse:返回给客户端的HTTP响应报文
c 复制代码
System.out.println("浏览器发起了一次请求");
System.out.println(servletRequest.getClass().getName());//记录请求对象的类名。
System.out.println(servletResponse.getClass().getName()); //记录响应对象的类名。

3.1 使用HttpServletRequest,处理HTTP请求

在后端查看请求信息

java 复制代码
/*写在service方法中*/
System.out.println("我是service");
// 将通用的ServletRequest对象转换为更具体的HttpServletRequest对象,以便可以访问HttpServletRequest特有的方法和属性。
HttpServletRequest request = (HttpServletRequest) servletRequest;
System.out.println("请求使用的协议: " + request.getProtocol());// 打印请求使用的协议
System.out.println("客户端的IP地址: " + request.getRemoteAddr()); // 打印客户端的IP地址
System.out.println("请求的URI: " + request.getRequestURI());// 打印请求的URI
System.out.println("打印请求的方法(如GET、POST): " + request.getMethod());// 打印请求的方法(如GET、POST)
// 获取头部信息
// 获取请求头的所有名称
Enumeration<String> enumration = request.getHeaderNames();
// 遍历所有请求头名称,并打印其对应的值
while (enumration.hasMoreElements()) {
    String name = enumration.nextElement();// 获取请求头名称
    String value = request.getHeader(name);// 获取当前名称对应的值
    System.out.println(name + "--->" + value);// 打印请求头名称和值
}

运行结果

3.2 使用HttpServletResponse,编写响应内容

java 复制代码
/*写在service方法中*/
// 将Servlet响应转换为HTTP响应对象,以便更直接地操作响应头和内容。
HttpServletResponse response=(HttpServletResponse) servletResponse;
// 设置响应头的Content-Type,指定响应内容类型为HTML,编码为UTF-8。
response.setHeader("Content-Type","text/html;charset=UTF-8");
// 将指定的HTML内容写入响应体。
response.getWriter().write("<h1>我是响应内容!</h1>");

3.3 继承HttpServlet,简化开发

核心思想:重写HttpServlet中的方法,简化JavaWeb项目的开发

类的继承关系:类HttpServlet 继承 类GenericServlet 实现 接口Servlet

  • GenericServlet没有实现service

3.3.1 直接访问,会执行doGet(),显示方法不可用

3.3.2 重写doGet()方法后,会执行重写后doGet()方法

java 复制代码
@WebServlet("/test")
public class TestServlet extends HttpServlet {
	//重写doGet()方法
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().write("<h1>恭喜你解锁了全新玩法</h1>");
    }
}


3.4 @WebServlet注解,怎么写

注解的作用:把这个类注册为Servlet,之后该类会按Servlet的方式运行。

注解中的参数:这个Servlet运行时的一些配置

常用tips

  • *代表任意

3.4.1 指定访问的URL

此处URL是/test/任意字符,如/test,/test/123,/test/456asdf

java 复制代码
@WebServlet("/test/*")  //  URL: /test/任意字符
@WebServlet(value = "/test/*")  //  另一种写法,更全

3.4.2 指定文件后缀

java 复制代码
// 解释:获取以.html结尾的文件时,会调用这个Servlet
@WebServlet("*.html")
// 解释:获取以.js结尾的文件时,会调用这个Servlet
@WebServlet("*.js")

3.4.3 特殊URL

/代表若Tomcat没有找到对应的URL,则进入这个路由(一般是404)

  • 注:前缀URL必须正确,如
java 复制代码
@WebServlet("/")

3.4.4 配置多个URL

java 复制代码
@WebServlet({"/test1","/test2"})

3.4.5 Servelet在项目启动时是否加载(init方法)

  • loadOnStartup = 1加载
    • 数字代表启动顺序,顺序:1,2,3,....
  • loadOnStartup = -1不在启动时加载,在被访问时才会加载
java 复制代码
//写了多个参数,要用 name=value 格式
@WebServlet(value = {"/t21","/t22"},loadOnStartup = 2)

3.4.6 其他参数

怎么看?

查看@WebServlet的定义即可

4、用Post请求实现登录

实现一个登录页面+功能,代码见下方链接。

简易的Web登录功能(Servlet,mybatis,MySQL)

5、Servlet实现文件的上传/下载

JavaWeb文件上传/下载(Servlet)

6、前端XHR请求数据

  • 页面上的部分内容,动态显示
  • 如:时间旁有个按钮,点击按钮可刷新时间

前端XHR请求数据

7、重定向VS请求转发

7.1 重定向

  • 登陆后,跳转到主页
  • 关键:resp.sendRedirect("main");
  • 流程
    • 前端:输入账号密码,登录,访问/login
    • 后端:执行/login的doPost(),执行重定向
    • 前端:收到重定向响应(状态码302),访问主页/main
    • 后端:执行/main的doGet(),返回主页面的页面html

基础程序:简易的Web登录功能(Servlet,mybatis,MySQL)

修改1:登录成功

修改2:创建类MainServlet

手动设置重定向

java 复制代码
//自动重定向
resp.sendRedirect("main");//执行重定向
//手动重定向
resp.setStatus(302);
resp.setHeader("Location", "main");
//重定向到百度
resp.setStatus(302);
resp.setHeader("Location", "https://www.baidu.com");

7.2 请求转发:

  • 后端内部转发
  • req.getRequestDispatcher("/main").forward(req,resp);
  • 流程
    • 前端:输入账号密码,登录,访问/login
    • 后端:执行/login的doPost(),执行请求转发
    • 后端:执行/main的doPost(),返回主页面信息
    • 前端:接收到主页面信息,显示

基础程序:简易的Web登录功能(Servlet,mybatis,MySQL)

修改1:登录成功

修改2:创建类MainServlet

对比

重定向 请求转发
前端发起请求次数 2 1
前端地址栏变化 不变
能否共享请求参数 不能
只能转发给项目内的Servlet

8、ServletContext对象

ServletContext是个全局变量,属于整个Web App,可通过getServletContext()获取

功能1:传递数据(键值对)

存储数据:

java 复制代码
// 获取Servlet上下文对象,该对象在整个Web应用程序中都是唯一的
ServletContext context = getServletContext();
// 设置一个属性"test_data",并赋值为"我是数据test_data"
// 这个属性可以在Web应用的任何地方访问,只要拥有对ServletContext的引用
// 这种方式常用于在多个Servlet之间共享数据,或者存储配置信息
context.setAttribute("test_data", "我是数据test_data");

获取数据:

java 复制代码
// 获取Servlet上下文对象,该对象在整个Web应用程序中都是唯一的
ServletContext context = getServletContext();
// 从Servlet上下文中尝试获取之前设置的"test_data"属性的值
// 如果存在该属性,将打印其值;否则,将打印null
System.out.println(context.getAttribute("test_data"));

功能2:请求转发

java 复制代码
// 获取Servlet上下文对象,该对象在整个Web应用程序中都是唯一的
ServletContext context = getServletContext();
// 使用Servlet上下文的Dispatcher来转发请求到"/main"路径的资源
// 这将导致请求和响应对象被传递给"/main"路径所映射的Servlet或JSP页面
// 请求转发是一个服务器端操作,客户端浏览器不会看到实际的URL改变
// "/main"应该是Web应用内部的一个有效路径,例如一个Servlet或JSP页面
context.getRequestDispatcher("/main").forward(req, resp);

9、初始化参数

在Servlet中存储初始化参数,如

  • 数据库连接信息:账号,密码,url
  • 系统设置:如缓存策略、日志级别、邮件服务器设置
  • APIKey:如高德地图,百度AI等的APIKey

9.1 Servlet中的初始化参数

格式(键值对形式)

java 复制代码
@WebServlet(value = "/login", initParams = {
        @WebInitParam(name = "test", value = "我是初始化参数test")//初始化参数在这
})

通过getInitParameterNames()方法获取初始化参数的"名称"(name)

java 复制代码
// 获取初始化参数的名称枚举
Enumeration<String> paramNames = getInitParameterNames();
// 遍历并输出所有初始化参数的名称
while (paramNames.hasMoreElements()) {
//while (paramNames.hasMoreElements())检查枚举是否还有未处理的元素(即参数名)。
//如果有的话,paramNames.nextElement()会获取下一个参数名,并将其赋值给paramName。
    String paramName = paramNames.nextElement();
    System.out.println(paramName);
}

通过Servlet的getInitParameter()方法获取初始化参数

java 复制代码
//根据name获取value
System.out.println(getInitParameter("test"));

9.2 全局初始化参数

web.xml编写

xml 复制代码
<context-param>
    <param-name>test_quanjv</param-name>
    <param-value>我是全局初始化参数</param-value>
</context-param>

ServletContext来读取全局初始化参数:

java 复制代码
/**
 * 获取Web应用程序的ServletContext对象。
 * ServletContext对象代表了整个Web应用程序的上下文环境。
 * 之后,从ServletContext对象中获取名为"test_quanjv"的初始化参数的值。
 * 如果该参数存在,其值将被输出到控制台。
 */
ServletContext context = getServletContext();
// 输出名为"test_quanjv"的初始化参数的值
System.out.println(context.getInitParameter("test_quanjv"));

参考

https://www.itbaima.cn/document/ycpagby2v7j4p728

相关推荐
wfsm13 小时前
flowable使用01
java·前端·servlet
六件套是我1 天前
redission实现延时队列
android·java·servlet
非典型代码3 天前
Jenkins发不出邮件
运维·servlet·jenkins
佐杰3 天前
Jenkins安装部署
运维·servlet·jenkins
chxii4 天前
Spring Boot 中,内嵌的 Servlet 容器(也称为嵌入式 Web 服务器)
spring boot·servlet
BUG?不,是彩蛋!4 天前
Maven-Java 项目到底解决了什么痛点?
java·servlet·maven
CS Beginner8 天前
【搭建】个人博客网站的搭建
java·前端·学习·servlet·log4j·mybatis
一只小透明啊啊啊啊10 天前
Java Web 开发的核心组件:Servlet, JSP,Filter,Listener
java·前端·servlet
芙蓉王真的好111 天前
优化 Jenkins 构建脚本:避免 pnpm lockfile 相关报错的关键配置
spring·servlet·jenkins
要站在顶端11 天前
Jenkins Pipeline 多job依赖、触发多Job、并行执行及制品下载
运维·servlet·jenkins