Servlet+JSP实现web应用程序

上一篇博客介绍了Servlet的基础知识,此篇博客通过实际例子来演示如果搭配Servlet和JSP编写web应用程序,如果对ServletJSP基础知识不清楚,可查看这里了解基础知识。另外,web Demo应用中还使用了Bootstrap,Bootstrap基础知识可查看这里Demo代码地址。Demo中主要实现了四个模块功能:注册、登陆、添加/修改/删除TodoList,TodoList展示。

因为Demo中使用了Mysql数据库, 所以下载Demo代码后,需要安装Mysql,创建DB,并用script.sql中的脚本初始化数据库DB,JDBCUtils中修改数据库连接信息(用户名和密码)。Demo代码非常简单,其中dao和model主要用于对数据库数据进行增删改查,Controller Class都是Servlet的Class,JDBCUtils编写了连接数据库的代码。以LoginController为例子,继承了HttpServlet Class,里面overwrite了doGet()和doPost()方法。

JSP文件都存放在webapp目录下,以login.jsp文件为例,form表单的action=<%=request.getContextPath()%>/login,这里的含义是提交form表单后,执行/login这个url请求,上面LoginController在@WebServlet("/login")中指定的url也是"/login",另外form中method指定的是post,所以当提交login form表单时,执行的是LoginController中doPost()方法。该方法执行了authenticate(request,response)方法,也就是对输入的用户名和密码进行校验,查看是否在数据库中,如果存在则跳转到todo-list页面,如果不存在则继续在login.jsp页面。另外,Demo中的JSP文件都引入了bootstrap,关于bootstrap的更多基础知识可查看这里

可以看到采用JSP+Servlet组合的方式很容易编写Web应用,对于前端样式部分,可以引入bootstrap来实现。上面介绍了Demo,接下来看看Servlet背后的工作原理,首先来看看Servlet接口规范。Servlet接口定义了5个方法。

其中最重要的是service方法,具体业务类在这个方法里实现处理逻辑。这个方法有两个参数:ServletRequest和ServletResponse。ServletRequest用来封装请求信息,ServletResponse用来封装响应信息,因此本质上这两个类是对通信协议的封装。比如HTTP 协议中的请求和响应就是对应了HttpServletRequest和HttpServletResponse这两个类。接口中还有两个跟生命周期有关的方法init和destroy,Servlet容器在加载Servlet类的时候会调用init方法,在卸载的时候会调用destroy 方法。可以在init方法里初始化一些资源,并在destroy方法里释放这些资源,比如Spring MVC中的DispatcherServlet,就是在init方法里创建了自己Spring容器。你可能还会注意到ServletConfig这个类,ServletConfig 的作用就是封装 Servlet 的初始化参数。你可以在web.xml给Servlet配置参数,并在程序里通过getServletConfig方法拿到这些参数。

当客户请求某个资源时,HTTP 服务器会用一个 ServletRequest 对象把客户的请求信息封装起来,然后调用 Servlet 容器的 service 方法,Servlet 容器拿到请求后,根据请求的 URL 和 Servlet 的映射关系,找到相应的 Servlet,如果 Servlet 还没有被加载,就用反射机制创建这个 Servlet,并调用 Servlet 的 init 方法来完成初始化,接着调用 Servlet 的 service 方法来处理请求,把 ServletResponse 对象返回给 HTTP 服务器,HTTP 服务器会把响应发送给客户端。如果是Http请求,那么集成HttpServlet,overwrite的主要是doGet和doPost方法。

Servlet 容器会实例化和调用 Servlet,那 Servlet 是怎么注册到 Servlet 容器中的呢?一般来说,我们是以 Web 应用程序的方式来部署 Servlet 的,而根据 Servlet 规范,Web 应用程序有一定的目录结构,在这个目录下分别放置了 Servlet 的类文件、配置文件以及静态资源,Servlet 容器通过读取配置文件,就能找到并加载 Servlet。Web 应用的目录结构大概是下面这样的:

引入Servlet 规范后,你不需要关心 Socket 网络通信、不需要关心 HTTP 协议,因为这些都被 Servlet 规范标准化了。为此,针对个性化的需求Servlet还提供了两种扩展机制Filter和Listener

Filter是过滤器,这个接口允许你对请求和响应做一些统一的定制化处理,比如你可以根据请求的频率来限制访问,或者根据国家地区的不同来修改响应内容。过滤器的工作原理是这样的:Web 应用部署完成后,Servlet容器需要实例化Filter并把Filter链接成一个 FilterChain。当请求进来时,获取第一个Filter并调用doFilter方法,doFilter方法负责调用这个FilterChain中的下一个Filter。如下所示:通过@WebFilter注解方式添加Filter的自定义逻辑,doFilter方法中编写具体的自定义逻辑。

Listener是监听器,这是另一种扩展机制。当Web应用在Servlet容器中运行时,Servlet容器内部会不断的发生各种事件,如Web应用的启动和停止、用户请求到达等。 Servlet容器提供了一些默认的监听器来监听这些事件,当事件发生时,Servlet 容器会负责调用监听器的方法。当然,你可以定义自己的监听器去监听你感兴趣的事件,将监听器配置在web.xml中。Servlet 3.0 提供了3 个注解:@WebServlet:用于声明一个 Servlet。@WebFilter:用于声明一个 Filter @WebListener:用于声明一个 Listener。如下所示:implement了ServletRequestListener和ServletContextListener两个Listener。

启动应用后,可以看到执行了Lisenter中定义的逻辑,在浏览器中访问任意请求时,会执行RequestListener中的逻辑。

实际项目中Servlet也有很多场景在使用,例如链路追踪系统,需要在代码中传递parentId、traceId、spanId,为了传递这些信息,对于一个微服务的前端服务部分,就可以在doFilter()方法中将这些信息添加到Header中,这样其他服务调用的时候就可以通过header信息获取到这些id,继续往下传递,如下所示:是使用CAT完成链路追踪时,添加的传递ID的逻辑。更多使用CAT完成链路追踪的内容可查看这篇文章

除了链路追踪系统会使用,一些网关工具也会使用,例如Zuul1.0就是利用Servlet实现网关相关功能的,下图是Zuul1.0架构图。更多关于Zuul使用的文章可以查看这里

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

taoli-qiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值