【JavaWeb】Servlet开发流程

一、需求

校验注册时,用户名是否被占用。通过客户端向一个Servlet发送请求,携带username,如果用户名是 'atguigu',则向客户端响应 NO,如果是其他,响应YES


二、创建Web项目

image-20240727143152852


三、引入servlet-api依赖

一共有三种方法

1)引入到父项目中

在父项目的根目录新建lib文件夹,然后将servlet-api引入。

这种情况是在很多个Module共享的,默认情况下和module是没有关系的。

第一步:右击,将它添加为库

image-20240303203252513

然后从子项目中引用它

image-20240303203509169

加进来后,表示这个module依赖这个Library,但是这个Module里有一个artifact部署包,它是已经生成了。

  • 方法一:将artifact删掉,重新建一个

  • 方法二:点击Problems,将lib加入进入

image-20240727142509904


2)引入到模块中(推荐)

在当前项目的 web\WEB-INF 下新建lib文件夹,导入 servlet-api

缺点:只能是当前 module 独享。如果有第二个 module,我们需要再次重复的新建 lib

优点:启动项目的时候会自动将lib加进去


3)将Tomcat依赖加入进来

找到库(Library),将tomcat依赖导入进来

image-20240727143509165

查看外部库,可以看见tomcat库已包含了servlet-api

image-20240727143555182

三种导入方式对比

如果使用第二种方式进行导入,那么就就需要手动进行构建

image-20240727163102916

并且需要将IDEA构建好的App手动发布到Tomcat中

image-20240727163326746

此时就会出现部署包和Tomcat的lib下有相同一份jar包。

Tomcat的lib目录不仅仅用于Tomcat本身,还用于所有部署进Tomcat所共享的jar包。

回忆一下:

lib:Tomcat的类库,里面是一大堆jar文件。如果需要添加Tomcat依赖的jar文件,可以把它放到这个目录中,当然也可以把应用依赖的jar文件放到这个目录中,这个目录中的jar所有项目都可以共享,但这样你的应用放到其他Tomcat下时就不能再共享这个目录下的jar包了,所以建议只把Tomcat需要的jar包放到这个目录下;

解释:Tomcat本身也是用java和c写的程序,它本身也是一个项目,所以它本身也依赖一些jar包类;而且Tomcat编译和构建后,就会产生很多很多的jar文件,因此这里面就可以理解为它是Tomcat程序本身的一些jar包。

但是我们并不会将部署的项目所依赖的jar包放到这个lib里,因为这个lib中是公用的,但是并不是所有的项目都需要这个lib中的所有的jar包。

image-20240727163502434

不仅会出现jar包重复,而且还有可能会发生依赖冲突。


但如果只在当前项目导入Tomcat的依赖,旁边的Provided表示依赖的作用域。

main目录(空间)test目录(空间)开发过程(时间)部署到服务器(时间)
provided有效有效有效无效

provided:在开发过程中需要用到的 "服务器上的jar包" 通常以 provided 范围依赖进来。比如 servlet-api、jsp-api。而这个范围的 jar 包之所以不参与部署、不放进 war 包,就是避免和服务器上已有的同类 jar 包产生冲突,同时减轻服务器的负担。说白了就是:服务器上已经有了,你就别带啦!

image-20240727165414356

因此我们通过这种方式导入进来的依赖,我们只是在编码的时候有这个依赖,真正进行项目构建和打包的时候,它是不携带Tomcat所导进来的jar包的。

image-20240727165559330

但如果后续我们需要导MySQL的jar包、druid的jar包,那还是需要往 WEB-INF/lib 中放的,因为服务器不提供。


四、开发一个UserServlet

  • 自定义一个类,本来是需要实现Servlet接口,但是Servlet接口中方法中太多了,但我们只需要重写service方法,因此我们可以继承HttpServlet类:HttpServlet继承了GenericServlet抽象类,而GenericServlet抽象类实现了Servlet接口,因此HttpServlet也就间接的实现了Servlet接口
  • 重写service方法,该方法主要就是用于处理用户请求的服务方法
  • HttpServletRequest 代表请求对象,是由请求报文经过tomcat转换而来的,通过该对象可以获取请求中的信息
  • HttpServletResponse 代表响应对象,该对象会被tomcat转换为响应的报文,通过该对象可以设置响应中的信息
  • Servlet对象的生命周期(创建,初始化,处理服务,销毁)是由tomcat管理的,无需我们自己new
  • HttpServletRequest、HttpServletResponse 两个对象也是由tomcat负责转换,再调用service方法时传入给我们用的

src/com/atguigu/servlet/UserServlet.java

/*
 * servlet 开发流程
 * 1 创建 javaWEB 项目,同时将 tomcat 添加为当前项目的依赖
 * 2 重写 service 方法  service(HttpServletRequest req, HttpServletResponse resp)
 * 3 在 service 方法中,定义业务处理代码
 *
 */
public class UserServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1 从request对象中获取请求中的任何信息(username参数)
        // form表单请求过来的有可能是get请求方式(?后key=value),也有可能是post请求方式(请求体里key=value),但不管是哪种请求方式,都是key=value
        String username = request.getParameter("username"); // 根据参数名获取参数值,无论参数是在url后,还是在请求体中,只要是键值对形式的,都可以获取到

        // 2 处理业务的代码
        String info = "YES";
        if (!"atguigu".equals(username)) {
            info = "NO";
        }

        // 3 将更响应的数据放入response
        // 该方法返回的是一个向响应体中打印字符串的打印流,你通过这个流进行数据输出的时候,数据会放到response存储响应体的那个区间
        PrintWriter writer = response.getWriter();
        writer.write(info);
    }
}

五、在 web.xmlUseServlet 配置请求的映射路径

1)代码示例

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0">

    <servlet>
        <!--给UserServlet起一个别名-->
        <servlet-name>userServlet</servlet-name>
        <servlet-class>com.atguigu.servlet.UserServlet</servlet-class>
    </servlet>


    <servlet-mapping>
        <!--关联别名和映射路径-->
        <servlet-name>userServlet</servlet-name>
        <!--可以为一个Servlet匹配多个不同的映射路径,但是不同的Servlet不能使用相同的url-pattern-->
        <url-pattern>/userServlet</url-pattern>
       <!-- <url-pattern>/userServlet2</url-pattern>-->
        <!--
            /        表示通配所有资源,不包括jsp文件
            /*       表示通配所有资源,包括jsp文件
            /a/*     匹配所有以a前缀的映射路径
            *.action 匹配所有以action为后缀的映射路径
        -->
       <!-- <url-pattern>/*</url-pattern>-->
    </servlet-mapping>

</web-app>

2)使用问题

  • Servlet 并不是文件系统中实际存在的文件或者目录,所以为了能够请求到该资源,我们需要为其配置映射路径
  • servlet 的请求映射路径配置在 web.xml
  • servlet-name 作为servlet的别名,可以自己随意定义,见名知意就好
  • url-pattern 标签用于定义Servlet的请求映射路径
  • 一个servlet可以对应多个不同的 url-pattern
  • 多个servlet不能使用相同的 url-pattern

一个 <servlet-name> 允许对应多个 <servlet-pattern>,无论请求的是哪个 <url-pattern>,都会对应到 Demo02Servlet

<servlet-mapping>
 <servlet-name>Demo02Servlet</servlet-name>
 <url-pattern>/demo02</url-pattern>
 <url-pattern>/demo03</url-pattern>
</servlet-mapping>

但是一个 <url-pattern> 不能对应多个 <servlet-name>


一个servlet允许对应多个servlet-mapping,无论发给哪个 <url-pattern>(但是url-pattern互相需要不同),都是对应一个servlet。这样可以在servlet当中获取我们到底是通过哪个URL请求过来的。根据不同URL发送的请求,可以执行不同的业务逻辑。

<servlet>
 <servlet-name>Demo02Servlet</servlet-name>
 <servlet-class>com.atguigu.servlets.Demo02Servlet</servlet-class>
</servlet>

<servlet-mapping>
 <servlet-name>Demo02Servlet</servlet-name>
 <url-pattern>/demo02</url-pattern>
</servlet-mapping>
<servlet-mapping>
 <servlet-name>Demo02Servlet</servlet-name>
 <url-pattern>/demo021</url-pattern>
</servlet-mapping>
<servlet-mapping>
 <servlet-name>Demo02Servlet</servlet-name>
 <url-pattern>/demo022</url-pattern>
</servlet-mapping>

但是一个servlet-mapping不能对应多个servlet

既然两种方式都可以,那不如使用第一种方式,这样就不需要写很多个 <servlet-mapping> 了。


3)特殊写法

上面我们写的都是 url-pattern 的精确匹配, url-pattern 中可以使用一些通配写法进行模糊匹配

表达式描述
/通配所有资源, 不包括jsp文件
/*通配所有资源, 包括jsp文件(就算这个jsp文件已经有了,也会被这个Servlet所匹配到,从而不走jsp文件)
/a/*匹配所有以a前缀的映射路径,多级路径也是可以匹配的
*.action匹配所有以 .action 为后缀的映射路径
1.不要写成 /*.action,因为 /* 已经是全部资源了,.action 已经没有意义了,并且写成 /*.action 会报错
2.前面有多个路径也是可以匹配到的 /a/b/c/xxx.action

六、开发一个form表单,向servlet发送一个get请求并携带username参数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!-- http://127.0.0.1:8080/demo02/userServlet -->

<!-- 请求体
username=zhangsan
-->

<form method="get" action="userServlet">
    用户名:<input type="text" name="username"><br>
    <input type="submit" value="校验">
</form>

</body>
</html>

七、启动项目,访问index.html,提交表单测试

将部署的项目改为 web02

image-20240727151133097

使用debug模式运行测试,如果就写到 http://127.0.0.1:8080/web02,它默认就是去找index.html | index.htm | index.jsp

image-20240727151751681

在表单中填入 atguigu,点击测试,此时断点就会生效

image-20240727153156168


八、流程 & 映射关系图

  1. 用户发请求:action="userServlet"
  2. 服务器(tomcat,项目)中,web.xml中找到servlet-mapping中的url-pattern = /userServlet
  3. servlet-name = userServlet
  4. 找和servlet-mappingservlet-name一致的servlet
  5. 找到servlet中的servlet-class就能通过 <servlet> 找到 com.atguigu.servlet.userServlet
  6. tomcat会将字节码文件加载进内存,并且通过反射创建其对象
  7. 然后 tomcat 执行userServlet实例中的service方法

1681550398774

image-20240727194828298

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值