JavaWeb 组件-Servlet
前序
web目录结构说明
src 目录用来存放Java代码(servlet...),web目录下存放页面jsp,html ,css等文件,web-inf 下存放配置文件web.xml。
http协议,https协议
http和https协议是浏览器与服务器之间进行通信的协议,基于tcp协议。HTTPS协议是在HTTP的基础之上通过SSL进行加密的安全通信协议。HTTP默认端口号80,HTTPS默认端口号443。
Servlet
servlet 是JavaWeb最核心的组件,也是JavaWeb最基础和最要的组件。为什么要这么说呢。因为servlet 组件所要实现的功能是接收浏览器请求和向浏览器返回响应。它是浏览器与服务器之间沟通的桥梁。servlet属于MVC框架的controller,servlet是整个JavaWeb的基石。
Servlet的实现
servlet 的实现方式有两种
- 实现servlet接口,重写service方法来实现。
- 继承HttpServlet类,来实现servlet。
通过实现servlet接口来实现自定义Servlet类
public class FirstServlet 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 {
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
servlet 接口定义了5个方法,我们关注的核心在service 方法,service 方法为我们提供了两个比较重要的参数 servletrequest,servletresponse。通过这两个参数,我们就可以轻松的实现获取浏览器传递的参数和向浏览器响应我们的处理结果。当然这个结果可以是视图,也可以为一段交互的数据信息,比如json。我们可以通过在service的方法体中编写代码,完成我们的处理逻辑。
通过继承HttpServlet类来实现servlet
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
通过HttpServlet来实现servlet,我们只需要继承HttpServlet类,来重写HttpServlet类中的方法我们就能实现我们处理请求返回响应的目的。这里有细节,就是HttpServlet类中参数的类型与Servlet接口中参数类型不同,HttpServlet类中是HttpRequest/HttpServletResponse而Servlet接口中是ServletRequest/ServletResponse。这是什么原因的。我们可以看一下这两个类的关系。
HttpRequest是继承了servlet接口的接口。并进行了一些属性和方法的扩展。通过上面的图片,我们发现这两个都是接口,那么怎么可以实例化并且有方法体执行的呢。相信不少人都有这么个疑问。经过查找资料,其实原因是这样的:SUN只是规定这个类要实现HttpServletRequest接口,并且规定了各个方法的用途,但具体是什么类是由各个提供商自己决定的。简单的说就是sun公司通过接口定义了一种规范,具体实现有服务器提供者来实现,比如Tomcat,Jetty本身就实现了这两个接口。当我们使用时,tomcat利用==基于接口的动态代理==来为我们提供实现类来使用,屏蔽掉了底层具体实现细节。
现在我们在探究一下,为什么通过继承HttpServlet和实现Servlet接口都可以实现自定义的servlet类呢。我们来看一下它两的关系
通过UML类图我们可以清楚的看到Httpservelt继承了GenericeServlet,而GenericServlet实现了Servlet接口。所以我们可以通过HttpServlet来实现自定义的servlet。HttpServlet是对Servlet接口的扩展,所以更常用。特别需要注意的HttpServlet类和GenerircServlet是==抽象类==,不能直接实例化使用。
如何实现Servlet类的URL访问
通过上面我们已经掌握了如何去实现一个自己的Servlet类。那我们如何通过URL来访问到我们访问调用我们的Servlet类呢。其实有两种方式:
xml和注解。
xml
在动态web项目中我们有一个web.xml文件来让我进行Servlet的映射关系配置。
<!--servlet信息配置-->
<servlet>
<servlet-name>FirstServlet</servlet-name>
<servlet-class>com.stack.servlet.FirstServlet</servlet-class>
</servlet>
<!--servlet 映射信息-->
<servlet-mapping>
<servlet-name>FirstServlet</servlet-name>
<url-pattern>/firstServlet</url-pattern>
</servlet-mapping>
注意:这两对标签要成对出现
注解
只需要简单配置webservlet注解就可实现。web3.0后
@WebServlet(name = "twoServlet",urlPatterns = "/twoServlet")
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
补充
servlet生命周期
通过上面的Servlet的接口,我们可以观察到里面有init(),destory()方法,它们都是Servlet的生命周期函数
Servlet的生命周期
- 当我们第一次通过浏览器访问servlet时,web容器tomcat加载servlet通过构造函数初始化==单例多线程==的servlet对象,然后调用init()方法进行servlet的初始化(可以编写一些预处理操作)。
- 创建成功servlet后,我们每次访问servlet时都是只调用service方法执行。
- 当web应用关闭或关闭tomcat时,servlet调用destory()方法进行一些结尾操作(释放资源),然后对象被jvm回收。
- 补充:可以通过编辑Tomcat配置文件在Tomcat一启动就加载创建加载Servlet对象。
servlet中还存在一些关于描述本身属性的方法可供我们使用。如: getServletInfo()——获取servlet的信息。
方法覆盖
在通过继承HttpServlet类来实现自定义Servlet时,service 方法的优先级比较高,service方法会覆盖掉doGet(),doPost(),doPut(),doDelete()等方法。