JavaWeb
Java Web 组件
首先献上Tomcat架构神图:
Servlet
-
Servlet容器:
运行在Web服务器上的程序,作为来自HTTP客户端的请求和HTTP服务器上的数据库或应用程序之间的中间层,它负责处理用户的请求,并根据请求生成相应的返回信息提供给用户。
大体原理图如下:
- Servlet请求的处理过程:
- 浏览器发起http请求
- Servlet容器收到请求后,分别创建了HttpServletRequest对象和HttpServletResponse对象
- Servlet容器调用HttpServlet的init方法,init方法只在第一次请求时被调用
- Servlet容器读取HttpServletRequest对象中读取信息,然后通过service()方法处理请求信息,根据请求信息找到对应的路由(业务逻辑)
- 处理完后将处理信息封装到HttpServletResponse对象,然后返回
- 容器关闭时,调用destory函数
- Servlet生命周期
-
服务器启动时(web.xml中配置load-on-startup=1,默认为0)或者第一次请求该servlet时,就会初始化一个Servlet对象,也就是会执行初始化方法init(ServletConfig conf)。
-
servlet对象去处理所有客户端请求,在service(ServletRequest req,ServletResponse res)方法中执行
-
服务器关闭时,销毁这个servlet对象,执行destroy()方法。
-
由JVM进行垃圾回收。
Filter
- Filter过滤器:
Filter也称为过滤器,主要功能是在HttpServletRequest对象到达Servlet之前,拦截、检查该对象,同时也可以对该HttpServletRequest对象的头部数据进行相应的修改;同时,也会拦截HttpServletResponse,修改对象中的数据
通俗来讲就是用来过滤网站数据,用于处理中文乱码、登录验证等操作...
- Filter工作原理:
1、Filter 程序是一个实现了特殊接口的 Java 类,与 Servlet 类似,也是由 Servlet 容器进行调用和执行的。
2、当在 web.xml 注册了一个 Filter 来对某个 Servlet 程序进行拦截处理时,它可以决定是否将请求继续传递给 Servlet 程序,以及对请求和响应消息是否进行修改。
3、当 Servlet 容器开始调用某个 Servlet 程序时,如果发现已经注册了一个 Filter 程序来对该 Servlet 进行拦截,那么容器不再直接调用 Servlet 的 service 方法,而是调用 Filter 的 doFilter 方法,再由 doFilter 方法决定是否去激活 service 方法。
4、但在 Filter.doFilter 方法中不能直接调用 Servlet 的 service 方法,而是调用 FilterChain.doFilter 方法来激活目标 Servlet 的 service 方法,FilterChain 对象时通过 Filter.doFilter 方法的参数传递进来的。
5、只要在 Filter.doFilter 方法中调用 FilterChain.doFilter 方法的语句前后增加某些程序代码,这样就可以在 Servlet 进行响应前后实现某些特殊功能。
6、如果在 Filter.doFilter 方法中没有调用 FilterChain.doFilter 方法,则目标 Servlet 的 service 方法不会被执行,这样通过 Filter 就可以阻止某些非法的访问请求。
- 生命周期:
Listener
监听,当涉及某个接口的操作时,会调用相关函数
-
ServletContextListener:对Servlet上下文的创建和销毁进行监听; ServletContextAttributeListener:监听Servlet上下文属性的添加、删除和替换;
-
HttpSessionListener:对Session的创建和销毁进行监听。Session的销毁有两种情况,一个中Session超时,还有一种是通过调用Session对象的invalidate()方法使session失效。
-
HttpSessionAttributeListener:对Session对象中属性的添加、删除和替换进行监听;
-
ServletRequestListener:对请求对象的初始化和销毁进行监听; ServletRequestAttributeListener:对请求对象属性的添加、删除和替换进行监听。
Maven
存在的必要性
- 手动导入:
点击项目结构
然后选择路径导入
- 使用Maven导入
我们可以通过pom.xml中编写xml条目统一导入库
配置
- 去官网下载,这不用说了吧
- 编辑环境变量
去Maven官网下载,然后编辑环境变量
- 配置镜像源
在conf/setting.xml中写入
- 配置仓库地址
同样位置下写入如下条目
- 在IDEA中配置Maven
使用
pom.xml:Maven的核心配置文件,记录该项目的信息
Maven的相关功能及其IDEA UI下的相关操作演示
一个项目中一般包含三个模块:生命周期、插件、依赖
Tomcat
Tomcat主要功能
tomcat作为web服务器,主要有两个核心组件
Connector(连接器): HTTP服务器功能,进行Socket通信(基于TCP/IP),解析HTTP报文
Container(容器):Servlet容器功能:加载和管理Servlet,由Servlet具体负责处理Request请求
Connector连接器
Connector由如下组件构成:
- EndPoint:进行socket通信,将字节写入字节的输入流中然后传给Processor,或者将字节输出流转化成字节
- Processor:将字节流对象转成Request对象,或者将Response对象转成字节流对象
- Adapter:将Request对象解析成ServletRequest对象
Endpoint与Processor有一个组合名称为ProtocolHandler
Container容器
在Container中有四种容器:
- Engine 表示整个 Catalina 的 Servlet 引擎,用来管理多个虚拟站点,一个 Service 最多只能有一个 Engine,但是一个引擎可包含多个 Host
- Host 代表一个虚拟主机,或者说一个站点,可以给 Tomcat 配置多个虚拟主机地址,而一个虚拟主机下可包含多个 Context
- Context 表示一个 Web 应用程序,每一个Context都有唯一的path,一个Web应用可包含多个 Wrapper
- Wrapper 表示一个Servlet,负责管理整个 Servlet 的生命周期,包括装载、初始化、资源回收等
JavaWeb组件 + Tomcat 开发
Servlet
(严重踩坑:注意Tomcat + Servlet + Java 的版本匹配问题,可以参考:https://tomcat.apache.org/whichversion.html)
使用方法如下:
-
继承
HttpServlet
抽象类,然后重写doGet
等方法 -
注册Servlet,路由映射:
-
在高版本的Servlet中可以使用@WebServlet注解指明路由
-
低版本中在web.xml中注册Servlet,然后声明对应路由
-
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet()
public class HelloServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ServletOutputStream outputStream = resp.getOutputStream();
PrintWriter writer = resp.getWriter(); // 响应流
writer.print("Hello,Serlvet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
web.xml
<web-app>
<display-name>Archetype Created Web Application</display-name>
<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>
</web-app>
Filter
Filter:过滤器,用来过滤网站的数据
- 处理中文乱码
- 登录验证
Filter:
package filter;
import javax.servlet.*;
import java.io.IOException;
import javax.servlet.Filter;
public class TestFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException{
System.out.println("Test Filter Init");
System.out.println(System.currentTimeMillis());
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException{
servletResponse.getWriter().write("Before TestFilter:\n");
System.out.println("Before TestFilter:");
System.out.println(System.currentTimeMillis());
filterChain.doFilter(servletRequest, servletResponse);
servletResponse.getWriter().write("After TestFilter\n");
System.out.println("After TestFilter");
System.out.println(System.currentTimeMillis());
}
public void destroy(){
System.out.println("Test Filter Destroy");
System.out.println(System.currentTimeMillis());
}
}
web.xml
<filter>
<filter-name>TestFilter</filter-name>
<filter-class>filter.TestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/show</url-pattern>
</filter-mapping>
Listener
步骤:
- 实现监听器的接口
- 在web.xml中配置路由
实现接口:
package listener;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class OnlineCountListener implements HttpSessionListener {
// 创建session监听(session创建时会触发这个函数)
public void sessionCreated(HttpSessionEvent sessionEvent) {
System.out.println("SessionCreated");
// 获取session上下文
ServletContext ctx = sessionEvent.getSession().getServletContext();
// 读
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if(onlineCount == null){
onlineCount = new Integer(1);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
// 写
ctx.setAttribute("OnlineCount",onlineCount);
}
// 销毁session监听(session销毁时会触发这个函数)
public void sessionDestroyed(HttpSessionEvent sessionEvent){
System.out.println("SessionDestroyed");
ServletContext ctx = sessionEvent.getSession().getServletContext();
// 读
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if(onlineCount == null){
onlineCount = new Integer(0);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
// 写
ctx.setAttribute("OnlineCount",onlineCount);
}
}
web.xml
<listener>
<listener-class>listener.OnlineCountListener</listener-class>
</listener>