Javaweb开发中有很重要的三个组件分别是:Servlet,Filter,Listener。这些组件在Javaweb的开发中起着不同且至关重要的作用,而我们常用的web框架基本都是基于这些基础组件进行封装之后的用法,所以对于这些原生的方式进行Javaweb开发也要需要了解的,这样对框架的认识也能更加深入,理解为什么要那么做。
1.Serlvet的广义概念
Servlet是运行在服务器容器中的一个小程序,所有的用户请求最终都会汇入这里,然后根据请求,通过url交给不同的Servlet对象去处理,也就是业务逻辑的核心部分。
2.Servlet的作用
Servlet在Javaweb担当核心的作用,最核心的业务逻辑是在Servlet对象中进行处理,然后返回给用户的,也是我们最需要关注的组件。
3.Servlet的狭义概念
但是其实Servlet在Java中就是一个有5个抽象方法的接口而已,通过实现这个接口构建不同的Servlet类,处理不同的业务请求。
这就是那个神奇的Servlet最本来的样子。
这几个函数去看api就知道了,下面主要演示一个Servlet的简单例子,看看怎么使用Servlet来进行web的开发。
4. Servlet的基本使用
首先是使用最基本的Servlet接口来实现访问一个url,然后返回success,顺便说一下Servlet的一些xml设置和生命周期
1. 首先需要实现Serlvet接口来创建一个Serlvet类,这样才能创建对象(接口不能实例化,应该都知道吧)
public class ServletDemo implements Servlet{
//对象销毁时调用
@Override
public void destroy( ){
System.out.println("Servlet has been destroyed");
}
//这个方法一般不用管
@Override
public ServletConfig getServletConfig(){
return null;
}
//这个方法一般不用管
@Override
public String getServletInfo(){
return null;
}
//做Servlet的一些初始化操作,在Serlvet实例创建的同时调用
@Override
public void init(ServletConfig servletConfig)throws ServletException{
//测试ServletConfig对象是否接收到xml里面配置的参数
String username = servletConfig.getInitParameter("username");
System.out.println("username: "+ username);
System.out.println("Servlet has been created");
}
//这个是Servlet里面最重要的函数,通过这个函数来处理对应的请求的业务
// 这里可以去学习ServletRequest和ServletResponse这两个类,整个web的前后端交互都是基于Request和Response的
@Override
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException{
response.getWriter().write("success");
}
}
这样用一个类ServletDemo来实现了我们最原始的Serlvet接口,这样这个SerlvetDemo就具备处理请求的能力了,但是处理是谁的请求,又是如何映射到这个类的实例上的呢?
接下来配置Servlet另一个很重要的部分,就是web.xml
servletDemo
com.lyh.servlet.ServletDemo
username
lyh
password
112233
1
servletDemo
/ServletDemo
这里的xml就配置了我们访问"项目路径/ServletDemo”的时候,会将请求转到ServletDemo这个name的Servlet实例去处理,然后就去找name为ServletDemo的实例,然后发现找到了,对应的类是com.lyh.Servlet.ServletDemo这个用户创建的类。那么就会去创建一个这个类的对象(一般方便起见,都称为Servlet实例),调用init方法。
此时这个Servlet的生命周期就开始了,通过自己的Service方法来处理从各个ip发来的Http请求,只要是对这个url的请求,都会转给他来处理,知道服务器关闭的时候,这个Servlet实例就被销毁了,然后destroy方法被调用,Servlet实例生命周期结束。
这样一个基础的web响应就完成了,通过Servlet,Java里比较原生的方式实现了。
但是我们发现Servlet这个接口直接实现使用有很多不方便的地方,而且我们一般只是和Http协议进行交互,Java设计者自然也想到了这一点,所以在javax.servlet库中已经有为Http协议专门设计的一个类,HttpServlet。
5.HttpServlet的基本使用
HttpServlet类继承自GenericServlet类,GenericServlet类实现了Servlet接口,ServletConfig接口和Serializable接口。这里的源码也比较简单,建议去读读源码。既然有ServletConfig了,那就能用ServletContext这个全局的东西。
下面用HttpServlet来做一个简单的web应用,就可以看到这个这个类比Servlet接口好用多了。
HttpServlet里有很多方法,我们需要重写的一般是doGet(),doPost(),init()等等这些方法,因为在HttpServlet中,通过Service方法实际上调用的都是doGet()和doPost()这样的方法,来对Http协议中具体的方法进行业务处理。
先写一个HttpServletDemo类,继承自HttpServlet类,重写了doGet()和init()方法(重写那个方法是有讲究的,还是建议去读源码,就是看最后调用到那个方法然后父类将这个方法空了下来,那么我们就需要去重写的是这个方法)
public class HttpServletDemo extends HttpServlet{
@Override
public void init() throws ServletException {
System.out.println("HttpServlet has been Created");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//测试ServletConfig对象是否接收到xml里面配置的参数
ServletContext sc = getServletContext();
System.out.println(sc);
//测试向ServletContext中添加数据,进行读取和更新
if(sc.getAttribute("count") == null){
sc.setAttribute("count", 1);
}else{
int count = (int) sc.getAttribute("count");
sc.setAttribute("count", count+1);
}
Integer count = (Integer) sc.getAttribute("count");
resp.getWriter().write(count.toString());
}
@Override
public void destroy() {
super.destroy();
System.out.println("HttpServlet has been destroyed");
}
}
这里可以看到和前面的方式不同的,一个是我们重写的是doGet()方法不再是service方法,这是由于基类为我们细分了请求类型;另外是使用了ServletContext这个对象,至于具体的说明,看下面的web.xml吧
test
hello
servletDemo
com.lyh.servlet.ServletDemo
username
lyh
password
112233
1
servletDemo
/ServletDemo
HttpServletDemo
com.lyh.servlet.HttpServletDemo
HttpServletDemo
/HttpServletDemo
这个就是HttpServlet的基本使用,实际web开发中不同的知识doGet()方法要处理的业务逻辑更加复杂罢了,为了方便业务处理等,大牛们封装了Servlet而形成了框架。
最后根据Serlvet的生命周期我们知道Servlet实例是单例的,而且没有同步处理,所以是线程不安全的。