Servlet简介
Java Servlet是运行在Web服务器或应用服务器上的程序,它是作为来自Web浏览器或其他HTTP客户端的请求和HTTP服务器上的数据库或应用程序之间的中间层。
使用Servlet,可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。Java Servlet通常情况下与使用CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。
Servlet可以使用javax.servlet和 javax.servlet.http包创建,它是Java企业版的标准组成部分,Java企业版是支持大型开发项目的Java类库的扩展版本。
Servlet架构
Servlet的架构如下所示:
备注:这里的HTTP Server可以是Tomcat/Jetty等。
Java Servlet HelloWorld程序
(1)编写HelloWorld Servlet程序
1 | import java.io.*; |
(2)在tomcat中配置做Servlet的映射
按如下内容修改tomcat web.xml配置:
1 | <web-app> |
(3)启动tomcat并测试
在浏览器中输入http://127.0.0.1/HelloWorld
即可访问。如下:
Servlet的生命周期
JAVA Servlet WEB应用程序部署规范
根据J2EE Servlet规范,WEB应用程序有特定的目录结构,将Servlet应用程序部署到Servlet容器(Tomcat/Jetty等)时必须按照这样的目录结构部署,具体结构如下:
当我们使用Eclipse等IDE工具创建WEB工程时,IDE会自动在webapp目录下按照这样的目录结构给开发者组织WEB应用。web.xml很重要,一般使用了Spring等框架时,该配置文件中定义了框架的核心Servlet。
需要注意的是,JAVA Web应用部署到容器后,/WEB-INF/classes/和/WEB-INF/lib/目录都属于CLASSPATH中一部分,JAVA Web应用可以直接使用这些目录中jar包中的类。
备注:我们构建项目生成的WAR包就是这个目录结构,WAR包是可以直接扔到Servlet容器(Tomcat/Jetty等)中被加载起来的。另外WAR包中也可以有META-INF的目录,该目录中会有MANIFEST.MF文件,该文件的内容同普通JAR中是一样的。这里要注意WAR包和JAR包的结构是有差比的。简单来说,WAR包是Java Web程序打的包,WAR包里面包括写的代码编译成的class文件,依赖的包,配置文件,所有的网站页面,包括html/jsp等等,一个WAR包可以理解为是一个WEB项目,里面是项目的所有东西。
其他闲杂知识
(1)Listener
监听器Listener,它是实现了javax.servlet.ServletContextListener接口的服务器端程序,它是随web应用的启动而启动,只初始化一次,随web应用的停止而销毁。主要作用是做一些初始化的内容添加工作、设置一些基本的内容、比如一些参数或者是一些固定的对象等等。在Servlet被Servlet容器初始化之前,可以向Servlet容器注册一些Listener来执行一些前置的工作逻辑,该Listener需要继承自javax.servlet.ServletContextListener。比如Spring 框架的监听器ContextLoaderListener会在服务器启动的时候实例化我们配置的bean对象、hibernate的session的监听器会监听session的活动和生命周期,负责创建,关闭session等活动。
以Spring的ContextLoaderListener举例来说:
1 | <web-app> |
(2)Filter
Filter是一个可以复用的代码片段,可以用来转换HTTP请求、响应和头信息。Filter不像Servlet,它不能产生一个接收请求或者响应请求,它只是修改对某一资源的请求,或者修改对某一资源的响应。Servlet/JSP规范中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码、做一些业务逻辑判断等。
JSP
在使用Servlet时,若想给浏览器返回HTML页面,那我们在Servlet中代码中插入HTML页面的字符串,那一个简单的页面都很复杂(当然现在结合模版引擎也很方便啦):
JSP全称Java Server Pages,是一种动态网页开发技术。它使用JSP标签在HTML网页中插入Java代码。标签通常以<%
开头,以%>
结束。实际上jsp页面的本质还是Servlet,只不过是为了方面画界面所单独拉出来的一部分而已,到最终的实现还是会回到Servlet当中。
Servlet容器通过解析其中Servlet的别名,再找到对应的Servlet并执行其中的service方法做出处理和响应,那么对于Servlet容器来说它只认识Servlet,那么我们编辑的Jsp到底是如何被服务器识别的?实际上Servlet容器还是将*.jsp
当作Servlet的别名在你局部配置下的web.xml找有没有对应的Servlet,如果没有找到对应的Servlet就去Tomcat的公共配置下的web.xml(Tomcat安装目录conf下的web.xml)找对应的Servlet。会找到如下内容:
org.apache.jasper.servlet.JspServlet会将对应的jsp文件转为Servlet。假设一个test.jsp文件内容如下:
1 | <%@ page language="java" contentType="text/html; charset=utf-8" |
被org.apache.jasper.servlet.JspServlet转换成Servlet后,内容如下:
1 | /* |
但是我们发现这个类并没有继承HttpServlet而是继承了org.apache.jasper.runtime.HttpJspBase并且里面也没有service方法而是_jspservice
方法。那么Tomcat就会到它的父类中找service方法并进行调用。实际上它的父类org.apache.jasper.runtime.HttpJspBase继承了HttpServlet。
jsp已经是一门比较落后的技术来,因为html、css、js是前端写的,而后端要在其中加入逻辑判断,那么首先你一定得认识前端语言的代码,否则你如何嵌套?这样很不利于前后端的分离。之所以学习是因为很多框架和项目中依然会用到它,但是最终还是会被时代所淘汰。