1. Servlet介绍
1.1 Servlet定义
- Servlet是JavaEE规范(接口)之一,是JavaWeb三大组件之一
- Servlet是与平台无关的服务器组件,运行在Servlet容器中。Servlet容器负责Servlet与客户端的通信及调用Servlet的方法
- Servlet是运行在服务器上的一个小型java程序,可以接收客户端发送过来的请求,并响应数据给客户端
- Servlet可以创建并返回基于用户请求的动态HTML页面、创建可嵌入到现有HTML页面中的部分HTML片段、与其他服务器资源进行通信
- Servlet广义上时Sun公司的一套技术标准,狭义上是javax.servlet.Servlet接口及其子接口
1.2 手动创建Servlet程序
- 导入Servlet相应jar包或maven依赖
- 编写一个类实现Servlet接口
- 实现service方法,处理请求,并响应数据
- 在web.xml中配置Servlet程序的访问地址
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- <servlet>标签:给Tomcat配置Servlet程序
- <servlet-name>标签:Servlet程序的别名
- <servlet-class>标签:Servlet程序的全类名
- <servlet-mapping>标签:给某个名字的Servlet程序配置访问地址
- <url-pattern>标签:配置资源路径(访问地址)
实现Servlet接口需要重写的方法:
public void init(ServletConfig servletConfig)
public ServletConfig getServletConfig()
public void service(ServletRequest servletRequest, ServletResponse servletResponse)
public String getServletInfo()
public void destroy()
1.3 Servlet的生命周期
- 执行Servlet构造器方法
- 执行init初始化方法:第1、2步在第一次创建Servlet程序时调用
- 执行service方法:每次访问时都会调用
- 执行destroy销毁方法:在web工程停止时调用
1.4 请求的分发处理
根据service方法中传入的ServletRequest接口类型参数,可根据其子接口HttpServletRequest得到请求的方式,不同方式的请求给予不同操作。(若使用Chrome浏览器,访问一次Servlet页面可能执行两次请求,多出的一次get请求是由于浏览器插件引起的)
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String method = httpServletRequest.getMethod();
if ("GET".equals(method)){
System.out.println("get请求");
}else if ("POST".equals(method)){
System.out.println("post请求");
}
2. Servlet接口结构
2.1 Servlet接口的子类
Servlet接口有两个抽象类GenericServlet和HttpServlet,一般在实际项目开发中,都是使用继承HttpServlet类的方式去实现Servlet程序,并重写doGet()和doPost()方法在不同请求方式时调用。(若通过IDEA直接创建Servlet,创建的类会继承于HttpServlet,并自动重写doGet()和doPost()方法)
2.2 ServletConfig类
ServletConfig类是Servlet程序的配置信息类,其作用有:
- 可以获取Servlet程序的别名,即<servlet-name>的值
- 获取初始化参数,即<init-param>,该标签在配置文件中是<servlet>的子标签,属于某个Servlet工程
- 获取ServletContext对象
String servletName = servletConfig.getServletName();
String username = servletConfig.getInitParameter("username");
ServletContext servletContext = servletConfig.getServletContext();
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
- Servlet程序和ServletConfig对象都是由Tomcat负责创建
- Servlet程序默认在第一次访问时创建;ServletConfig在每个Servlet程序创建时,就创建一个对应的ServletConfig对象
- GenericServlet抽象类在init()方法中保存了ServletConfig对象,若Servlet程序中重写init()方法,需要调用super.init()保证ServletConfig对象能够使用
2.3 ServletContext接口
2.3.1 ServletContext介绍
- ServletContext表示Servlet上下文对象
- 一个web工程,只有一个ServletContext对象实例
- ServletContext对象是一个域对象(域对象是可以像map一样存取数据的对象,域指存取数据的操作范围,为整个web工程)
- ServletContext在web工程部署启动时创建,在web工程停止时销毁
存数据 | 取数据 | 删除数据 | |
---|---|---|---|
map | put() | get() | remove() |
域对象 | setAttribute() | getAttribute() | removeAttribute() |
2.3.2 ServletContext的作用
- 获取web.xml中配置的上下文参数,即<context-param>,该标签在配置文件中是与<servlet>同级的标签,属于整个web工程
- 获取当前的工程路径
- 获取工程部署后在服务器磁盘上的绝对路径
- 像map一样存取数据
ServletContext servletContext = getServletConfig().getServletContext();
String username = servletContext.getInitParameter("username");
String contextPath = servletContext.getContextPath();
// 斜杠被服务器解析地址为:http://ip:port/工程名/
String realPath = servletContext.getRealPath("/");
servletContext.setAttribute("key1", "value1");
<context-param>
<param-name>username</param-name>
<param-value>context</param-value>
</context-param>
2.4 Servlet中参数和属性的区别
- 来源不同:参数是从客户端(浏览器)中由用户提供的;属性是由服务器端的组件用setAttribute()方法设置的
- 操作不同:参数的值只能读不能改,通过getParameter()读取;属性的值既可以读也可以改
- 数据类型不同:客户端的参数值只能是简单类型,服务器获取参数时统一以String类型看待;属性的值可以是任意Object类型
- 共同点:二者都被封装在request对象中
3. Http协议
3.1 Http协议介绍
- 协议指双方或多方相互约定好、大家都需要遵守的规则
- Http协议指客户端和服务器之间通信时需要遵守的规则
- Http协议中的数据又叫报文
- 客户端给服务器发送数据叫请求,服务器给客户端回传数据较响应
3.2 请求的Http协议
3.2.1 GET请求格式
- 请求行:① 请求的方式:GET;② 请求的资源路径+【?请求参数】;③ 请求协议的版本号:HTTP/1.1
- 请求头:由key:value组成
3.2.2 POST请求格式
- 请求行:与GET请求相同,除了请求方式改为POST
- 请求头:由key:value组成
- 请求体:发送给服务器的数据
3.2.3 常用请求头说明
- Accept:客户端可以接收的数据类型
- Accept-Language:客户端可以接收的语言类型
- User-Agent:客户端浏览器的信息
- Host:请求时服务器ip和端口号
3.2.4 GET请求和POST请求分类
- GET请求:① <form>标签method=get;② <a>标签;③ <link>标签引入css;④ <script>标签引入js文件;⑤ <img>标签引入图片;⑥<iframe>标签引入html页面;⑦ 在浏览器地址栏中输入地址后回车
- POST请求: <form>标签method=post
3.3 响应的Http协议
3.3.1 响应格式
- 响应行:① 响应的协议和版本号:HTTP/1.1;② 响应状态码:200;③ 响应状态描述符
- 响应头:由key:value组成
- 响应体:回传给客户端的数据
3.3.2 常用的响应码
- 200:请求成功
- 302:请求重定向
- 404:请求服务器已经收到,但是需要的数据不存在(请求地址错误)
- 500:请求服务器已经收到,但是服务器内部错误(代码错误)
3.4 MIME类型说明
MIME(多功能Internet邮件扩充服务)是HTTP协议中的数据类型,MIME的格式是“大类型/小类型”,并与某一种文件的扩展名相对应。常见的MIME类型有:
文件 | 文件扩展名 | MIME类型 |
---|---|---|
超文本标记语言 | .html | text/html |
普通文本 | .txt | text/plain |
GIF图形 | .gif | image/gif |
JPEG图形 | .jpeg,.jpg | image/jpeg |
4. 请求和响应接口
4.1 HttpServletRequest类
4.1.1 HttpServletRequest类的作用
每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中。然后传递到service()方法(doGet()和doPost()方法)中供使用,我们可以通过HttpServletRequest对象,获取到所有请求的信息。
4.1.2 HttpServletRequest类的常用方法
- getRequestURI():获取请求的资源路径
- getRequestURL():获取请求的统一资源定位符(绝对路径)
- getRemoteHost():获取客户端的ip地址
- getHeader(String key):获取请求头
- getParameter(String name):获取请求的参数
- getParameterValues(String name):获取请求的多个参数(如checkbox有多个参数)
- getMethod():获取请求的方式(GET或POST)
- setAttribute(String key, String value):设置域数据
- getAttribute(String key):获取域数据
- getRequestDispatcher(String):获取请求转发对象
4.1.3 请求的转发
服务器收到请求后,从一个资源跳转到另一个资源的操作叫请求的转发,其特点有:
- 浏览器地址栏没有变化
- 一次请求
- 多个Servlet程序共享Request域中的数据
- 可以转发到WEB-INF目录下
- 不能转发到当前工程以外的资源
//资源1
String username = req.getParameter("username");
System.out.println(username);
req.setAttribute("key1", "value1");
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/hello3");
requestDispatcher.forward(req, resp);
//资源2
String username = request.getParameter("username");
System.out.println(username);
Object key1 = request.getAttribute("key1");
System.out.println(key1);
4.1.4 <base>标签
相对路径在工作时都会参照当前浏览器地址栏中的地址来进行跳转,请求转发时地址栏不变,可能导致跳转到路径错误。<base>标签可以设置当前页面中所有相对路径工作时参照哪个路径来进行跳转,该标签作为<head>的子标签使用。
<base href="http://localhost:8080/Servlet/web/">
web中 / 斜杠的不同意义:
- / 如果被浏览器解析,得到的地址时:http://ip:port/
- / 如果被服务器解析,得到的地址时:http://ip:port/工程路径
- 特殊情况:使用response.sendRedirect("/")方法时,服务器会把斜杠发给浏览器解析(请求重定向)
4.2 HttpServletResponse类
4.2.1 HttpServletResponse类的作用
HttpServletResponse和HttpServletRequest类一样,每次请求进来,Tomcat服务器都会创建一个Response对象传递给Servlet程序使用。HttpServletResponse表示所有响应的信息,所有要返回给客户端的信息,都可以通过HttpServletResponse对象来设置。
4.2.2 两个响应流
HttpServletResponse对象调用方法可以获取两种输出流,这两个方法只能使用其中一个,否则报错:
- 字节流:getOutputStream()常用于下载,传递二进制数据
- 字符流:getWriter()常用于回传字符串
4.2.3 向客户端回传数据
服务器向浏览器回传数据时,为了使响应不出现乱码,必须保证两者使用的字符集一致。可通过修改服务器的字符集和回传响应头,或者同时修改。
//response.setCharacterEncoding("UTF-8");
//response.setHeader("Content-Type", "text/html;charset=UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
writer.write("响应内容");
4.2.4 请求重定向
客户端给服务器发送请求后,服务器让客户端去新地址访问,称为请求重定向。请求重定向时,旧资源需要向客户端返回响应状态码302,以及Location响应头,该响应头中包含新资源的地址。请求重定向特点有:
- 浏览器地址栏会发生变化
- 两次请求
- 不共享Request域中数据
- 不能重定向到WEB-INF目录下
- 能转发到当前工程以外的资源
//资源1
System.out.println("hello2");
//resp.setStatus(302);
//resp.setHeader("Location","http://localhost:8080/Servlet/hello3");
resp.sendRedirect("http://localhost:8080/Servlet/hello3");
//资源2
response.getWriter().write("hello3");
5. JavaEE三层架构
注意:使用maven进行导包时,需要将导入的包添加到WEB-INF目录下的lib目录中,否则Tomcat无法找到