什么是Servlet?
Servlet技术可以扩展服务器端的功能,让java代码在服务器端也能成为一种资源(动态资源),客户端浏览器可以通过指定的资源地址(URI),来访问这个java代码(Servlet),同时在Servlet代码中,还可以使用IO流把结果写回给浏览器。
按照Servlet规范要求,编写一个Servlet程序,只需要让自己的类实现 javax.servlet.Servlet 接口就可以了,但是该接口也有一些默认的实现类,所以除了实现接口的方式之外,我们也可以继承它默认的几个实现类,并且重写指定方法,也同样可以完成Servlet程序的编写。
javax.servlet.Servlet
它是Servlet技术的核心接口,所有的Servlet程序,都必须是该接口的实现类。
//Servlet接口
package javax.servlet;
import java.io.IOException;
public interface Servlet {
//初始化servlet对象的时候被调用
public void init(ServletConfig config) throws ServletException;
//返回ServletConfig对象,该对象封装了Servlet的配置信息
public ServletConfig getServletConfig();
//访问servlet对象的时候被调用(最重要的方法)
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
//返回servlet相关信息,比如作者、版本、版权等
public String getServletInfo();
//销毁servlet对象的时候被调用
public void destroy();
}
项目创建:Dynamic Web project
java Resources/src目录下编写代码
ps:三种方式都直接间接的实现了Servlet接口
* 客户端访问servlet
* url——请求行--访问Tomcat--读取web.xml--找到对应的Servlet程序
package com.briup.web.day02;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class TestServlet implements Servlet{
public TestServlet() {
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public ServletConfig getServletConfig() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getServletInfo() {
// TODO Auto-generated method stub
return null;
}
@Override
public void init(ServletConfig arg0) throws ServletException {
// 当对象创建成功后,会自动调用此初始化方法,并且只调用一次
}
/**
* 1.客户端访问servlet
* url——请求行--访问Tomcat--读取web.xml--找到对应的Servlet程序
*
*/
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
//1.根据请求信息获取请求的参数
String name=req.getParameter("name");
//2.进行逻辑处理
//3.将逻辑处理结果,响应给浏览器
res.setContentType("text/plain;charset=utf-8");
res.getWriter().append("hello 亲爱的"+name+" ,这是实现Servlet的第一种方式直接实现Servlet接口");
}
}
可以在web.xml中设置告诉tomcat,这个servlet对应的URI地址是什么,其实就是一种映射关系的配置也可以后面用@WebServlet()注解的方式,目的也是为了简化xml
web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>servlet_demodisplay-name>
<welcome-file-list>
<welcome-file>index.htmlwelcome-file>
<welcome-file>index.htmwelcome-file>
<welcome-file>index.jspwelcome-file>
<welcome-file>default.htmlwelcome-file>
<welcome-file>default.htmwelcome-file>
<welcome-file>default.jspwelcome-file>
welcome-file-list>
<servlet>
<servlet-name>testServletservlet-name>
<servlet-class>com.briup.web.day02.TestServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>testServletservlet-name>
<url-pattern>/testurl-pattern>
servlet-mapping>
web-app>
然后通过带参url地址:http://localhost:8080/servlet_demo/test?name=宇轩 访问这个Servlet
从浏览器控制台可以看出 响应头信息中的Content-Type字段值,就是我们在Servlet中进行设置的值
javax.servlet.GenericServlet
它是一个抽象类,它对Servlet接口中的方法进行了默认实现,但是最重要的 service 方法并没有实现
package javax.servlet;
import java.io.IOException;
import java.util.Enumeration;
public abstract class GenericServlet implements Servlet,ServletConfig,java.io.Serializable {
private static final long serialVersionUID = 1L;
private transient ServletConfig config;
public GenericServlet() {
// NOOP
}
@Override public void destroy() {
// NOOP by default
}
@Override public String getInitParameter(String name) {
return getServletConfig().getInitParameter(name);
}
@Override public Enumeration<String> getInitParameterNames() {
return getServletConfig().getInitParameterNames();
}
@Override public ServletConfig getServletConfig() {
return config;
}
@Override public ServletContext getServletContext() {
return getServletConfig().getServletContext();
}
@Override public String getServletInfo() {
return "";
}
@Override public void init(ServletConfig config) throws ServletException { this.config = config; this.init();
}
public void init() throws ServletException {
// NOOP by default
}
public void log(String msg) {
getServletContext().log(getServletName() + ": " + msg);
}
public void log(String message, Throwable t) { getServletContext().log(getServletName() + ": " + message, t);
}
@Override public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
@Override public String getServletName() {
return config.getServletName();
}
}
该类中,实现了Servlet接口中的init(ServletConfig config)方法,同时又重载了一个无参的init方法,并且有参数的init方法中又调用了这个重载的无参init方法。由此可知,将来我们对Servlet进行初始化操作的时候,重写这个无参的init方法即可。
package com.briup.web.day02;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
/**
* Servlet实现第二种
* 继承GenericServlet(Servlet实现类)其余四种方法它里
* 已经添加了实现逻辑,不需要再进行重写只需要实现其中的service方法
* @author 强宇轩
*
*/
@WebServlet("/test1")
public class TestServlet1 extends GenericServlet{
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
// TODO Auto-generated method stub
String name=req.getParameter("name");
res.setContentType("text/plain;charset=utf-8");
//获取输出流
PrintWriter out = res.getWriter();
//向输出流写入信息
out.println("hello!这是第二种方式:"+name); //使用流写出到浏览器
}
}
@WebServlet("/test1")相当于配置了xml,只是代替了xml中的映射配置
这种方式只用实现一个 service 方法即可,其他方法在父类中已经进行了默认实现
使用带参URl 访问 http://localhost:8080/servlet_demo/test1?name=宇轩
浏览器页面显示:hello!这是第二种方式:宇轩
javax.servlet.http.HttpServlet
/**它是一个抽象类,但是类中没有抽象方法。
它继承了 GenericServlet ,对接收到的客户端请求,进行了细分,对应不同的请求类型:
DELETE HEAD GET OPTIONS POST PUT TRACE
分别使用不同的方法进行处理。
例如,当前如果是GET请求,那么就调用doGet方法进行处理,当前如果是POST请求,那么就调用doPost
方法进行处理,所以在HttpServlet中,定义了很多doXxx方法,用来处理不同类型的请求。*/
HttpServlet继承了GenericServlet,实现了service方法,并且对service方法进行了重载
实现的service方法中,对请求和响应进行了强制类型转换,将普通的请求和响应对象,强制转换
成了针对HTTP协议的请求和响应,然后调用重载的service方法,将转换的请求和响应传入
重载后的service方法中,根据当前请求的类型(get、post获取其他),再调用对应的doXxx方法
进行处理
doXxx方法中会有一些默认的实现,例如doGet方法中会默认返回
http.method_delete_not_supported
我们编写子类继承 HttpServlet ,并且重写方法即可,如果需要处理GET方式的请
求,那么就重写doGet方法,如果需要处理POST方式的请求,那么就重写doPost方法。
package com.briup.web.day02;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/test2")
public class TestServlet2 extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
resp.setContentType("text/plain;charset=utf-8");
resp.getWriter().append("这是第三种方式:"+name);
}
}
总结:在service方法中 ServletRequest res 和ServletResponse req
表示 请求信息通过浏览器发送给tomcat后,然后由tomcat对字符串进行封装成请求对象。
ServletRequest 是一个Servlet中的接口 其实现类是tomcat提供的 (可类比于数据库厂商提供对于不同数据库连接的实现),其目的就是将面向协议开发—>转为面向对象开发
我们需要做的事就是 添加相应正文的操作