HTTP 协议
什么是 HTTP 协议
超文本传输协议(HTTP,HyperText Transfer Protocol),是互联网上应用最为广泛的一种网络协议,它是 TCP/IP 协议的一个应用层协议
简单来说,HTTP协议就是客户端和服务器交互的一种通迅的格式。
HTTP 请求
浏览器向服务器请求某个 web 资源时,称之为浏览器向服务器发送了一个 http 请求
请求方式有:POST、GET、HEAD、OPTIONS、DELETE、TRACE、PUT
- 常用的请求方式: POST、GET
一般来说,当用户点击超链接或通过地址栏访问某一网站资源,都是通过 GET 请求
而通过表单提交数据时则为 POST 请求
JavaWeb 项目
一个 IDEA 下的 Java Web 项目结构:
项目 project 目录:
project/out:项目部署后产生的 war 包
project/src:用于存放 Java 包(源码)和配置文件(例如数据库连接池的配置文件 c3p0-config.xml)
project/web:用于存放前端相关的文件(JSP、CSS、JavaScript)以及资源文件(图片、音频等)
project/WEB-INF/web.xml:web 配置文件
project/WEB-INF/lib:手动导入的 jar 包必须置于该目录下
project/index.jsp:默认主页面。启动服务器后,通过默认网络端口访问:localhost:8080
External Libraries/Tomcat:Tomcat 类库,需要导入 jsp-api.jar 和 servlet-api.jar 包
访问主页
project/web/index.jsp 是默认主页,JSP 文件基本等效于 HTML 文件
使用 IDEA 配置 Tomcat 服务器,修改应用程序上下文(Application Context)为:"/"
启动 Tomcat,目录中会出现 project/out 文件夹
此时访问 url:http://localhost:8080/
该 url 代表 out/artifacts/project_war_exploded 路径,这个路径会同步更新 web 目录中新建的 JSP 文件
实际上有:http://localhost:8080/ = http://localhost:8080/index.jsp
可以通过 http://localhost:8080/other.jsp 访问其他的 JSP 文件
如果应用程序上下文设置了路径,则须在 url 中加入相应的路径
例: http://localhost:8080/WIMS_war_exploded/index.jsp
Servlet
什么是 Servlet
JavaWeb 开发中与平台无关的服务器组件
Serlvet 是由服务器调用的,运行在 Servlet 容器(Web应用服务器/Tomcat)中
负责与客户端(Client)进行通信或与数据库(Database)交互
简单地说,Servlet 通常为 JavaWeb 服务器端程序的一个类
使用 Servlet
Servlet 本身是一组接口,由 javax.servlet 包提供
自定义一个类(class)并且实现 Servlet 接口,这个类就具备了接受客户端请求以及做出响应的功能
不过这个类必须对接口中的五种抽象方法进行重写:
public void init() // 初始化
public ServletConfig getServletConfig() // 获取 Servlet 配置文件内容
public void service() // 服务
public String getServletInfo() // 获取 Servlet 相关信息
public void destroy() // 销毁
Servlet 生命周期:
1、当浏览器访问 Servlet 时,Tomcat 会查询当前 Servlet 的实例化对象是否存在
如果不存在,则通过反射机制动态创建对象
如果存在,直接执行第3步
2、调用 init 方法完成初始化操作
3、调用 service 方法完成业务逻辑操作
4、关闭 Tomcat 时,调用 destroy 方法释放当前对象所占用的资源
浏览器没有权限访问该自定义类(Servlet 文件),因此要与 Servlet 进行通信,需要手动建立映射关系
建立映射的方法:
-
基于 web.xml 文件
-
基于 注解
基于 web.xml 文件
在 web/WEB-INF/web.xml 文件中添加映射代码
<servlet>
<servlet-name>ServletName</servlet-name>
<servlet-class>com.hjw.servlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletName</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
代码中,两组标签是一个映射关系。<servlet>
标签代表 java 类,<servlet-mapping>
标签代表 url 中的地址部分
两组标签中的 <servlet-name>
的值必须相同,可以为任意值
<servlet-class>
的值为 Servlet 在 project/src 下的路径
<url-pattern>
的值为访问该 Servlet 需要使用的 url
例如:(已修改 Tomcat 配置中 Application Context 的值为 “/”)
访问该 Servlet(MyServlet.java) 的 url 为:http://localhost:8080/MyServlet
优点:
- 可以将同一个 Servlet 映射到多个 url 上
<servlet>
<servlet-name>ServletName</servlet-name>
<servlet-class>com.hjw.servlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletName</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServletName</servlet-name>
<url-pattern>/TestServlet</url-pattern>
</servlet-mapping>
无论访问的是哪一个 url,都可以访问到目标 servlet
- 可以使用通配符
匹配所有:
<url-pattern>/*</url-pattern>
<url-pattern>/test/*</url-pattern>
匹配特定扩展名:
<url-pattern>*.jsp</url-pattern>
基于注解
配置格式:
import javax.servlet.annotation.WebServlet;
@WebServlet("/MyServlet")
public class MyServlet implements Servlet {
...
}
在 Servlet 类的前面添加注解:@WebServlet("/...")
配置要求:必须是以斜杠 “/” 开头的一个字符串
编译器编译时会将注解自动关联到 web.xml 中
在主机 url 后面添加该路径,即可在浏览器中访问 servlet
一个简单的交互实例
在 MyServlet.java 文件中重写 service 方法
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
String id = servletRequest.getParameter("id");
System.out.println("我是 Servlet,我接收到了参数:" + id);
servletResponse.setContentType("text/html;charset=UTF-8");
servletResponse.getWriter().write("Hello! Client!");
}
然后访问该文件,并在末尾添加 ?id=100
:http://localhost:8080/MyServlet?id=100
表示访问 url 的同时传递一个参数 id=100
控制台则会打印:我是 Servlet,我接收到了参数:100
HttpServlet 类
Servlet 接口的实现结构:
Servlet > GenericServlet > HttpServlet
GenericServlet 实现了 Servlet 接口,同时为它的子类屏蔽了不常用的方法,子类只需要重写 service 方法即可
HttpServlet 继承 GenericServlet 类,根据请求类型进行分发处理,GET 进入 doGet() 方法,POST 进入 doPost() 方法
开发者要自定义 Servlet 类,只需要继承 HttpServlet 并重写 doGet() 和 doPost() 方法即可
用 Servlet 类扩展 HttpServlet 类
@WebServlet("/test")
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("Hello World!");
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPut(req, resp);
}
}
当使用 http://localhost:8080/test 访问 Servlet 时,浏览器页面显示 “Hello World!”
关于 Serlvet 的一些细节
- Servlet 是单例的
浏览器多次对 Servlet 的请求,一般情况下,服务器只创建一个 Servlet 对象
也就是说,Servlet 对象一旦创建了,就会驻留在内存中,为后续的请求做服务,直到服务器关闭
因而,每次访问的请求对象和响应对象都是新的
对于每次访问请求,Servlet 引擎都会创建一个新的 HttpServletRequest 请求对象和一个新的 HttpServletResponse 响应对象,然后将这两个对象作为参数传递给它调用的 Servlet 的 service() 方法,service 方法再根据请求方式分别调用 doXXX 方法
ServletConfig 对象
每个 Servlet 实例都有一个独自的 ServletConfig,通过此对象可以读取web.xml中配置的初始化参数
方法:
getServletName() 返回 Servlet 的全类名(带有包名)
getInitParameter(String key) 获取 init 参数的值(基于web.xml)
getInitParameterNames() 返回所有的 initParameter 的 name 值,一般用于遍历初始化参数
getServletContext() 获取 ServletContext(上下文对象),是整个 Servlet 的管理者
ServletContext对象
当 Tomcat 启动的时候会创建一个 ServletContext 对象,作用于整个 Web 应用
作用:
1、所有 Servlet 都共享着一个 ServletContext 对象,因此 Servlet 之间可以通过 ServletContext 实现通讯。
ServletContext 对象可以被称之为域对象
实现Servlet之间通讯就要用到 ServletContext 的 setAttribute(String name,Object obj) 方法
第一个参数是关键字,第二个参数是要存储的对象
2、ServletConfig 获取的是配置于单个 Servlet 的参数信息,ServletContext 可以获取配置于整个 web 的参数信息
- web.xml 文件支持配置适用于整个 web 应用的参数
<context-param>
<param-name>name</param-name>
<param-value>xxx</param-value>
</context-param>
3、利用 ServletContext 读取 web 站点的资源文件(通过 ServletContext 获取 web 应用的主路径)
本地资源置于 Servlet 的同一目录下,在浏览器上也是无法访问的:FileNotFoundException 错误(HTTP Status 500)
因为所有的文件会被打包到 out 文件夹中,相对路径会发生改变,必须修改正确的绝对路径才能访问
而通过 ServletContext 则可以快速获取项目打包后的主路径,使代码看起来更加简洁(无需冗长的绝对路径)
4、实现 Servlet 的转发(不常用,转发主要用 request 实现)