Java Web 之 Servlet 100问
Filter 是什么?
在Java Web开发中,Filter(过滤器)是一种用于在请求到达目标资源(如Servlet、JSP)之前或响应返回客户端之前
进行预处理和后处理的组件。Filter可以拦截请求和响应,执行特定的操作,如日志记录、字符编码设置、身份验证、权限检查、数据压缩
等。Filter 可以将完成这些通用的操作,避免在多个 Servlet 中编写重复代码
。
Filter 中,什么是链式处理?
链式处理
:多个Filter可以串联,形成一个处理链,每个Filter依次处理请求和响应。
Filter 常见的应用场景有哪些?
常见应用场景:日志记录、字符编码设置、权限检查、身份验证
等。
Filter 的工作原理是什么?
客户端请求到达 → Filter 拦截并预处理 → 请求到达 Servlet ,Servlet 生成响应 → Filter 后处理 → 返回响应。
Filter 的生命周期分为哪些阶段?
init()
→ doFilter()
→ destroy()
Filter 的生命周期离不开以上三个方法,它们分别代表 Filter 的初始化 → 执行过滤操作 → 销毁
三个生命阶段。
如何实现一个 Filter?
实现javax.servlet.Filter
接口,并重写init()
、doFilter()
、destroy()
方法:
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;@WebFilter("/*") // 拦截所有请求
public class ExampleFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化操作}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 请求预处理System.out.println("Before processing request");// 传递给下一个Filter或目标资源chain.doFilter(request, response);// 响应后处理System.out.println("After processing response");}@Overridepublic void destroy() {// 销毁操作}
}
如何配置 Filter ?
可以通过注解(如@WebFilter
)或在web.xml
中配置Filter:
<filter><filter-name>ExampleFilter</filter-name><filter-class>com.example.ExampleFilter</filter-class>
</filter>
<filter-mapping><filter-name>ExampleFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
@WebFilter("/api/*")
会拦截哪些资源?
api/
路径下的所有资源都会被拦截。
@WebFilter("*.do")
会拦截哪些资源?
以.do
结尾的所有资源都会被拦截。
Listener 是什么?
在Java Web开发中,Listener(监听器)是一种用于监听Web应用中特定事件(如ServletContext、HttpSession、ServletRequest的创建、销毁或属性修改)的组件。Listener可以在这些事件发生时执行自定义逻辑,常用于初始化资源、统计在线用户、清理资源等场景。
Listener 的作用有哪些?
- 事件监听:监听Web应用中的各种事件,如应用启动、会话创建、请求到达等。
- 资源管理:在应用启动时初始化资源,在应用关闭时释放资源(如数据库连接等)。
- 日志记录:记录应用的关键事件,用于监控和调试。
- 初始化全局资源:在应用启动时初始化数据库连接池、缓存等。
- 统计在线用户数:跟踪用户会话状态,通过监听会话的创建和销毁,统计在线用户数。
Listener 常见的类型有哪些?
Java Web提供了多种Listener接口,用于监听不同的事件:
- ServletContextListener
- 监听
ServletContext
的创建和销毁。 - 常用方法:
contextInitialized()
、contextDestroyed()
。 - 应用场景:在应用启动时初始化全局资源(如数据库连接池),在应用关闭时释放资源。
- 监听
- HttpSessionListener
- 监听
HttpSession
的创建和销毁。 - 常用方法:
sessionCreated()
、sessionDestroyed()
。 - 应用场景:统计在线用户数、跟踪用户会话状态。
- 监听
- ServletRequestListener
- 监听
ServletRequest
的创建和销毁。 - 常用方法:
requestInitialized()
、requestDestroyed()
。 - 应用场景:记录请求日志、统计请求处理时间。
- 监听
- ServletContextAttributeListener
- 监听
ServletContext
中属性的添加、修改和删除。 - 常用方法:
attributeAdded()
、attributeRemoved()
、attributeReplaced()
。 - 应用场景:跟踪全局属性的变化。
- 监听
- HttpSessionAttributeListener
- 监听
HttpSession
中属性的添加、修改和删除。 - 常用方法:
attributeAdded()
、attributeRemoved()
、attributeReplaced()
。 - 应用场景:跟踪用户会话中属性的变化。
- 监听
- ServletRequestAttributeListener
- 监听
ServletRequest
中属性的添加、修改和删除。 - 常用方法:
attributeAdded()
、attributeRemoved()
、attributeReplaced()
。 - 应用场景:跟踪请求中属性的变化。
- 监听
Session 相关的监听器有哪些?
和Session相关的监听器有两种:
HttpSessionListener
- 监听
HttpSession
的创建和销毁。 - 常用方法:
sessionCreated()
、sessionDestroyed()
。 - 应用场景:统计在线用户数、跟踪用户会话状态。
HttpSessionAttributeListener
- 监听
HttpSession
中属性的添加、修改和删除。 - 常用方法:
attributeAdded()
、attributeRemoved()
、attributeReplaced()
。 - 应用场景:跟踪用户会话中属性的变化。
Request 相关的监听器有哪些?
Request相关的监听器有两种:
ServletRequestListener
- 监听
ServletRequest
的创建和销毁。 - 常用方法:
requestInitialized()
、requestDestroyed()
。 - 应用场景:记录请求日志、统计请求处理时间。
ServletRequestAttributeListener
- 监听
ServletRequest
中属性的添加、修改和删除。 - 常用方法:
attributeAdded()
、attributeRemoved()
、attributeReplaced()
。 - 应用场景:跟踪请求中属性的变化。
ServletContext 相关的监听器有哪些?
ServletContext相关的监听器有两种:
ServletContextListener
- 监听
ServletContext
的创建和销毁。 - 常用方法:
contextInitialized()
、contextDestroyed()
。 - 应用场景:在应用启动时初始化全局资源(如数据库连接池),在应用关闭时释放资源。
ServletContextAttributeListener
- 监听
ServletContext
中属性的添加、修改和删除。 - 常用方法:
attributeAdded()
、attributeRemoved()
、attributeReplaced()
。 - 应用场景:跟踪全局属性的变化。
Listener 如何实现?
要实现一个Listener,需要实现相应的接口,并重写其方法。例如,实现ServletContextListener
:
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;@WebListener
public class ExampleContextListener implements ServletContextListener {@Overridepublic void contextInitialized(ServletContextEvent sce) {// 应用启动时执行System.out.println("Web应用初始化");// 初始化全局资源,如数据库连接池}@Overridepublic void contextDestroyed(ServletContextEvent sce) {// 应用关闭时执行System.out.println("Web应用销毁");// 释放全局资源}
}
如何配置 Listener?
可以通过注解(如@WebListener
)或在web.xml
中配置Listener:
<listener><listener-class>com.example.ExampleContextListener</listener-class>
</listener>
Servlet 是什么?
Java Servlet | ||
---|---|---|
运行位置 | Web 服务器或应用服务器,如 Tomcat 等。 | |
主要功能 | 处理请求 | 处理客户端(一般是浏览器)发送的 HTTP 请求。 |
生成响应 | 生成动态Web内容,如 HTML、JSON 等。 | |
业务逻辑 | 在服务器端执行业务逻辑,如访问数据库、调用其他服务等。 | |
会话管理 | 管理客户端与服务器之间的会话,如使用Session、Cookie。 | |
本质 | Java程序 |
Servlet 的作用有哪些
作用 | |
---|---|
生成动态 HTML 页面 | 生成动态的 HTML 页面。 |
提供 Web 服务 | 提供 RESTful API 或 SOAP 服务。 |
文件上传和下载 | 处理文件上传和下载请求。 |
表单处理 | 处理用户提交的表单数据。 |
Servlet 的工作流程是什么?
流程 | 备注 |
---|---|
Servlet 容器(例如Tomcat)产生一个 Servlet 实例。 | 在一个应用程序中,每种Servlet类型只能有一个实例。同时产生一个 ServletContext 对象、一个 ServletConfig 对象。 |
用户发送 HTTP 请求。 | |
Servlet容器调用 Servlet 实例的service 方法。 | service 方法的参数 ServletRequest 对象和 ServletResponse 对象都是由 Servlet 容器封装好的,程序员可以直接使用这两个对象。 |
通过ServletRequest 获取 HTTP 请求。 | ServletRequest 中封装了当前的 HTTP 请求。 |
通过ServletResponse 返回响应内容。 | ServletResponse 表示当前用户的 HTTP 响应。 |
Servlet 的生命周期有哪些阶段
阶段 | 生命周期 | 备注 |
---|---|---|
阶段一 | 加载和实例化 | Web 容器加载 Servlet 类并创建其实例。 |
通常是在第一次收到请求时加载,但也可以通过配置在启动时加载。 | ||
阶段二 | 初始化 | 调用 init() 方法,完成 Servlet 的初始化工作。 |
开发者可以重写此方法,执行自定义的初始化逻辑(如加载配置文件、初始化数据库连接等)。 | ||
阶段三 | 处理请求 | 调用 service() 方法,处理客户端请求。 |
对于 HTTP 请求,通常会使用 HttpServlet 的子类,并重写 doGet() 、doPost() 等方法。 | ||
阶段四 | 销毁 | 调用 destroy() 方法,释放资源(如关闭数据库连接、清理缓存等)。 |
通常是在 Web 应用关闭或 Servlet 被移除时调用。 | ||
补充 | Servlet 的生命周期由 Web 容器(如 Tomcat)管理。 |
Servlet 的核心接口和类有哪些
13个核心接口和类 | 类型 | 所在 java 包 | 简介 |
---|---|---|---|
Servlet | 接口 | javax.servlet | 定义了 Servlet 的生命周期方法 |
void init(ServletConfig config) :初始化 Servlet。 | |||
void service(ServletRequest req, ServletResponse res) :处理请求。 | |||
void destroy() :销毁 Servlet。 | |||
ServletConfig getServletConfig() :获取 Servlet 配置信息。 | |||
String getServletInfo() :获取 Servlet 的描述信息。 | |||
GenericServlet | 抽象类 | javax.servlet | 提供了 Servlet 接口的基本实现,简化了 Servlet 的开发。 |
开发者可以继承此类,并重写 service() 方法。 | |||
HttpServlet | 类 | javax.servlet.http | 继承自 GenericServlet ,专门用于处理 HTTP 请求。 |
提供了对 HTTP 方法的支持(如 doGet() 、doPost() 、doPut() 、doDelete() 等)。 | |||
开发者通常继承此类,并重写相应的方法。 | |||
ServletRequest | 接口 | javax.servlet | |
HttpServletRequest | 接口 | javax.servlet.http | |
ServletResponse | 接口 | javax.servlet | |
HttpServletResponse | 接口 | javax.servlet.http | |
ServletConfig | 接口 | 封装 Servlet 配置。 | |
ServletDispatcher | 接口 | ||
ServletContext | 接口 | 封装了上下文(应用程序)的环境详情。 | |
Filter | 接口 | ||
Listener | 接口 |
Servlet 如何使用
导入Servlet
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope>
<!--提供provided 编译和测试有效,避免和 tomcat 中的 servlet-api 包冲突报错-->
</dependency>
以下是一个简单的 Servlet 示例,用于处理 HTTP GET 请求并返回 “Hello, World!”:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class HelloWorldServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {// 设置响应内容类型response.setContentType("text/html;charset=UTF-8");// 获取输出流PrintWriter out = response.getWriter();// 向客户端发送响应out.println("<html>");out.println("<head><title>Hello World</title></head>");out.println("<body>");out.println("<h1>Hello, World!</h1>");out.println("</body>");out.println("</html>");}
}
Servlet 如何配置
两种配置方式 | 介绍 |
---|---|
web.xml 配置 | 在 web.xml 文件中定义 Servlet 和映射 |
注解配置 | 使用 @WebServlet 注解定义 Servlet 和映射 |
(1) web.xml
配置
在 web.xml
文件中定义 Servlet 和映射:
<servlet><servlet-name>HelloWorldServlet</servlet-name><servlet-class>HelloWorldServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>HelloWorldServlet</servlet-name><url-pattern>/hello</url-pattern>
</servlet-mapping>
(2) 注解配置
使用 @WebServlet
注解定义 Servlet 和映射:
配置之后,我们就可以通过
http://localhost:8080/hello
访问Servlet。
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;@WebServlet(name = "HelloWorldServlet", urlPatterns = "/hello")
public class HelloWorldServlet extends HttpServlet {// Servlet 代码
}
Servlet 中的常用方法有哪些
七个相关的类或接口 | 常用方法 | |
---|---|---|
Servlet | void init(ServletConfig config) | 初始化 Servlet,容器在创建 Servlet 实例后调用此方法。 |
void service(ServletRequest req, ServletResponse res) | 处理客户端请求的核心方法。 | |
void destroy() | 销毁 Servlet,容器在移除 Servlet 实例前调用此方法。 | |
ServletConfig getServletConfig() | 返回 ServletConfig 对象,用于获取 Servlet 的配置信息。 | |
String getServletInfo() | 返回 Servlet 的描述信息(如作者、版本等)。 | |
GenericServlet | void init() | 无参的初始化方法,开发者可以重写此方法来实现自定义的初始化逻辑。 |
void log(String msg) | 将消息写入 Servlet 容器的日志文件。 | |
void log(String msg, Throwable t) | 将消息和异常信息写入 Servlet 容器的日志文件。 | |
HttpServlet | void doGet(HttpServletRequest req, HttpServletResponse resp) | 处理 HTTP GET 请求。 |
void doPost(HttpServletRequest req, HttpServletResponse resp) | 处理 HTTP POST 请求。 | |
void doPut(HttpServletRequest req, HttpServletResponse resp) | 处理 HTTP PUT 请求。 | |
void doDelete(HttpServletRequest req, HttpServletResponse resp) | 处理 HTTP DELETE 请求。 | |
void service(HttpServletRequest req, HttpServletResponse resp) | 根据请求方法(GET、POST 等)调用相应的 doXxx 方法。 | |
ServletRequest 和 HttpServletRequest | String getParameter(String name) | 根据参数名称获取请求参数的值。 |
String[] getParameterValues(String name) | 根据参数名称获取多个请求参数的值(适用于多选框等场景)。 | |
Map<String, String[]> getParameterMap() | 返回所有请求参数的键值对。 | |
String getHeader(String name) | 根据头名称获取请求头的值。 | |
Enumeration<String> getHeaderNames() | 返回所有请求头的名称。 | |
InputStream getInputStream() | 返回一个二进制输入流,用于读取请求体中的数据。 | |
BufferedReader getReader() | 返回一个字符输入流,用于读取请求体中的文本数据。 | |
void setAttribute(String name, Object obj) | 设置请求属性的名称和值。 | |
Object getAttribute(String name) | 根据名称获取请求属性的值。 | |
void removeAttribute(String name) | 移除指定的请求属性。 | |
ServletResponse 和 HttpServletResponse | void setContentType(String type) | 设置响应的内容类型(MIME 类型),例如 text/html 或 application/json 。 |
void setCharacterEncoding(String charset) | 设置响应的字符编码,例如 UTF-8 。 | |
ServletOutputStream getOutputStream() | 返回一个二进制输出流,用于向客户端发送二进制数据。 | |
PrintWriter getWriter() | 返回一个字符输出流,用于向客户端发送文本数据。 | |
void setHeader(String name, String value) | 设置响应头的名称和值。 | |
void addHeader(String name, String value) | 添加一个响应头,允许多个同名的头信息。 | |
void sendRedirect(String location) | 将客户端重定向到指定的 URL。 | |
void setStatus(int sc) | 设置响应的状态码(如 200、404 等)。 | |
注意 | getOutputStream() 和getWriter() | 不能同时调用,同时调用会发生异常。 |
示例代码
以下是一个简单的 Servlet 示例,展示了常用方法的使用:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class ExampleServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 设置响应内容类型和字符编码response.setContentType("text/html;charset=UTF-8");// 获取请求参数String username = request.getParameter("username");// 获取输出流PrintWriter out = response.getWriter();// 向客户端发送响应out.println("<html>");out.println("<head><title>Example Servlet</title></head>");out.println("<body>");out.println("<h1>Hello, " + (username != null ? username : "Guest") + "!</h1>");out.println("</body>");out.println("</html>");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 处理 POST 请求doGet(request, response);}
}
ServletRequest 的核心方法有哪些
获取请求参数
String getParameter(String name) | 根据参数名称获取单个请求参数的值。例如,获取表单中 name="username" 的值。 |
---|---|
String[] getParameterValues(String name) | 根据参数名称获取多个请求参数的值(适用于多选框等场景)。 |
Map<String, String[]> getParameterMap() | 返回所有请求参数的键值对,其中键是参数名称,值是参数值的数组。 |
获取请求头信息
String getHeader(String name) | 根据头名称获取单个请求头的值。例如,获取 User-Agent 或 Content-Type 。 |
---|---|
Enumeration<String> getHeaders(String name) | 根据头名称获取多个请求头的值(适用于多值的头信息)。 |
Enumeration<String> getHeaderNames() | 返回所有请求头的名称。 |
获取输入流
ServletInputStream getInputStream() | 返回一个二进制输入流,用于读取请求体中的数据(例如文件上传或二进制数据)。 |
---|---|
BufferedReader getReader() | 返回一个字符输入流,用于读取请求体中的文本数据(例如 JSON 或 XML)。 |
注意 | getInputStream 和 getReader 不能同时调用,否则会抛出 IllegalStateException 。 |
获取请求属性
void setAttribute(String name, Object obj) | 设置请求属性的名称和值。 |
---|---|
Object getAttribute(String name) | 根据名称获取请求属性的值。 |
void removeAttribute(String name) | 移除指定的请求属性。 |
Enumeration<String> getAttributeNames() | 返回所有请求属性的名称。 |
获取客户端和服务器信息
String getRemoteAddr() | 获取客户端的 IP 地址。 |
---|---|
String getRemoteHost() | 获取客户端的主机名。 |
int getRemotePort() | 获取客户端的端口号。 |
String getServerName() | 获取服务器的主机名。 |
int getServerPort() | 获取服务器的端口号。 |
String getProtocol() | 获取请求的协议(例如 HTTP/1.1 )。 |
String getScheme() | 获取请求的协议方案(例如 http 或 https )。 |
(6) 其他方法
String getContentType() | 获取请求体的内容类型(MIME 类型)。 |
---|---|
int getContentLength() | 获取请求体的长度(字节数)。 |
Locale getLocale() | 获取客户端的本地化信息。 |
Enumeration<Locale> getLocales() | 获取客户端支持的所有本地化信息。 |
使用示例
以下是一个简单的示例,展示如何使用 ServletRequest
获取请求参数并生成响应:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 设置响应内容类型response.setContentType("text/html;charset=UTF-8");// 获取请求参数String username = request.getParameter("username");// 获取字符输出流PrintWriter out = response.getWriter();// 向客户端发送响应out.println("<html>");out.println("<head><title>Hello Servlet</title></head>");out.println("<body>");out.println("<h1>Hello, " + (username != null ? username : "Guest") + "!</h1>");out.println("</body>");out.println("</html>");}
}
注意事项
- 参数编码:如果请求参数包含非 ASCII 字符(例如中文),需要设置正确的字符编码(例如
UTF-8
),否则可能出现乱码。可以通过request.setCharacterEncoding("UTF-8")
设置。 - 输入流的使用:根据请求体的数据类型选择
getInputStream
(二进制)或getReader
(文本)。 - 属性与参数的区别:请求参数是客户端发送的数据,而请求属性是服务器端设置的数据,用于在请求处理过程中共享信息。
ServletRequest
与 HttpServletRequest
是什么关系
父子接口 | HttpServletRequest 是ServletRequest 的子接口。 |
---|---|
HTTP 专用 | 专用于 HTTP 协议,提供了更多与 HTTP 相关的方法 |
新增特殊方法 | 获取 HTTP 方法(getMethod )。 |
获取请求的 URL 信息(getRequestURI 、getQueryString )。 | |
管理会话(getSession )。 | |
获取 Cookie(getCookies )。 | |
实际开发常用 | 在实际开发中,通常使用 HttpServletRequest ,因为它提供了更多 HTTP 相关的功能。 |
ServletResponse
的核心方法有哪些
以下是 ServletResponse
接口中一些重要的方法:
设置内容类型与字符编码
方法 | 介绍 |
---|---|
void setContentType(String type) | 设置响应的内容类型,如 text/html 或 application/json 。可附加字符编码,如 text/html;charset=UTF-8 。 |
void setCharacterEncoding(String charset) | 设置响应的字符编码,如 UTF-8 。若已经通过 setContentType 设置,则此方法会覆盖之前的设置。 |
获取输出流
方法 | 介绍 |
---|---|
ServletOutputStream getOutputStream() | 返回一个二进制输出流,用于向客户端发送二进制数据(例如图片、文件等)。 |
PrintWriter getWriter() | 返回一个字符输出流,用于向客户端发送文本数据(例如 HTML、JSON 等)。 |
注意 | getOutputStream 和 getWriter 不能同时调用,否则会抛出 IllegalStateException 。 |
设置响应头
方法 | 介绍 |
---|---|
void setHeader(String name, String value) | 设置响应头的名称和值,例如 setHeader("Content-Disposition", "attachment; filename=file.txt") 。 |
void addHeader(String name, String value) | 添加一个响应头,允许多个同名的头信息。 |
void setIntHeader(String name, int value) | 设置一个整数值的响应头。 |
缓冲区控制
方法 | 介绍 |
---|---|
void setBufferSize(int size) | 设置响应缓冲区的大小。 |
int getBufferSize() | 获取当前响应缓冲区的大小。 |
`void flushBuffer() | 强制将缓冲区的内容发送到客户端。 |
void reset() | 重置响应,清除缓冲区、状态码和头信息。 |
void resetBuffer() | 仅重置缓冲区的内容,不清除状态码和头信息。 |
boolean isCommitted() | 检查响应是否已经提交(即数据是否已经发送到客户端)。 |
其他方法
方法 | 介绍 |
---|---|
void setLocale(Locale loc) | 设置响应的本地化信息。 |
Locale getLocale() | 获取响应的本地化信息。 |
使用示例
以下是一个简单的示例,展示如何使用 ServletResponse
向客户端返回 HTML 内容:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class HelloWorldServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 设置内容类型和字符编码response.setContentType("text/html;charset=UTF-8");// 获取字符输出流PrintWriter out = response.getWriter();// 向客户端发送 HTML 内容out.println("<html>");out.println("<head><title>Hello World</title></head>");out.println("<body>");out.println("<h1>Hello, World!</h1>");out.println("</body>");out.println("</html>");}
}
注意事项
- 内容类型和字符编码:必须在调用
getWriter
或getOutputStream
之前设置内容类型和字符编码,否则设置可能无效。 - 输出流的选择:根据返回数据的类型选择
getWriter
(文本)或getOutputStream
(二进制)。 - 缓冲区管理:合理设置缓冲区大小,避免内存浪费或性能问题。
- 响应提交:一旦调用
flushBuffer
或缓冲区已满,响应就会被提交,之后无法修改状态码或头信息。
ServletResponse
与 HttpServletResponse
是什么关系
父子接口 | HttpServletResponse 是ServletResponse 的子接口。 |
---|---|
HTTP 专用 | 专用于 HTTP 协议,提供了更多与 HTTP 相关的方法 |
新增特殊方法 | 设置状态码(setStatus 、sendError )。 |
重定向(sendRedirect )。 | |
管理 Cookie(addCookie )。 | |
实际开发常用 | 实际开发中,通常使用 HttpServletResponse ,因为它提供了更多 HTTP 相关的功能。 |
Servlet
和ServletConfig
是什么关系
一对一 | 每个 Servlet 都有一个独立的 ServletConfig 对象,由 Servlet 容器(如 Tomcat)创建并传递给 Servlet。 |
---|---|
保存配置信息 | 通过 ServletConfig ,开发者可以访问 Servlet 的初始化参数、Servlet 上下文等信息。 |
ServletConfig
的核心方法有哪些
方法 | 介绍 | |
---|---|---|
获取初始化参数 | String getInitParameter(String name) | 根据参数名称获取 Servlet 的初始化参数值。如web.xml 中配置的 <init-param> 值 |
Enumeration<String> getInitParameterNames() | 返回所有初始化参数的名称。 | |
获取 ServletContext | ServletContext getServletContext() | 返回 ServletContext 对象,用于与 Servlet 容器通信。 |
获取 Servlet 名称 | String getServletName() | 返回 Servlet 名称。名称在 web.xml 中通过 <servlet-name> 配置,或注解 @WebServlet 指定。 |
使用示例
以下是一个简单的示例,展示如何使用 ServletConfig
获取初始化参数:
(1) 在 web.xml
中配置初始化参数
<servlet><servlet-name>MyServlet</servlet-name><servlet-class>com.example.MyServlet</servlet-class><init-param><param-name>username</param-name><param-value>admin</param-value></init-param><init-param><param-name>password</param-name><param-value>123456</param-value></init-param>
</servlet>
<servlet-mapping><servlet-name>MyServlet</servlet-name><url-pattern>/myservlet</url-pattern>
</servlet-mapping>
(2) 在 Servlet 中使用 ServletConfig
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MyServlet extends HttpServlet {private String username;private String password;@Overridepublic void init(ServletConfig config) throws ServletException {super.init(config);// 获取初始化参数username = config.getInitParameter("username");password = config.getInitParameter("password");}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();out.println("<html>");out.println("<head><title>MyServlet</title></head>");out.println("<body>");out.println("<h1>Username: " + username + "</h1>");out.println("<h1>Password: " + password + "</h1>");out.println("</body>");out.println("</html>");}
}
ServletConfig
与 ServletContext
的区别是什么
ServletConfig | ServletContext | |
---|---|---|
范围不同 | 每个 Servlet 有独立的 ServletConfig 。 | 整个 Web 应用共享一个 ServletContext 对象。在应用关闭时销毁。 |
用途不同 | 用于访问Servlet 的初始化参数。 | 用于访问 Web 应用的全局信息,如上下文初始化参数,资源路径等。 |
创建时机不同 | ServletConfig 对象在 Servlet 初始化时(init 方法调用时)创建 | 当 Web 服务器(如 Tomcat)启动并加载 Web 应用时创建。 |
线程安全 | 线程安全,可以在多线程环境中使用。 | 线程安全,可以在多线程环境中使用。 |
如何通过注解配置初始化参数
如果使用注解配置 Servlet,可以通过 @WebServlet
的 initParams
属性设置初始化参数:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@WebServlet(name = "MyServlet",urlPatterns = "/myservlet",initParams = {@WebInitParam(name = "username", value = "admin"),@WebInitParam(name = "password", value = "123456")}
)
public class MyServlet extends HttpServlet {private String username;private String password;@Overridepublic void init(ServletConfig config) throws ServletException {super.init(config);// 获取初始化参数username = config.getInitParameter("username");password = config.getInitParameter("password");}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();out.println("<html>");out.println("<head><title>MyServlet</title></head>");out.println("<body>");out.println("<h1>Username: " + username + "</h1>");out.println("<h1>Password: " + password + "</h1>");out.println("</body>");out.println("</html>");}
}
ServletContext的核心方法有哪些
作用 | 方法 | 介绍 |
---|---|---|
获取初始化参数 | String getInitParameter(String name) | 根据参数名称获取 Web 应用的初始化参数值。这些参数通常在 web.xml 中通过 <context-param> 配置。 |
- | Enumeration<String> getInitParameterNames() | 返回所有 Web 应用初始化参数的名称。 |
获取资源 | URL getResource(String path) | 根据路径获取资源的 URL。路径必须以 / 开头,相对于 Web 应用的根目录。 |
- | InputStream getResourceAsStream(String path) | 根据路径获取资源的输入流。适用于读取文件内容。 |
- | String getRealPath(String path) | 根据虚拟路径获取文件系统的真实路径。例如,将 /WEB-INF/web.xml 转换为服务器文件系统中的绝对路径。 |
- | Set<String> getResourcePaths(String path) | 返回指定路径下的所有资源路径。 |
共享数据(属性) | void setAttribute(String name, Object object) | 在应用范围内设置属性,让所有 Servlet 和请求都可以访问。 |
- | Object getAttribute(String name) | 根据名称获取应用范围内的属性。 |
- | void removeAttribute(String name) | 移除应用范围内的属性。 |
- | Enumeration<String> getAttributeNames() | 返回所有应用范围内的属性名称。 |
记录日志 | void log(String message) | 将消息写入 Servlet 容器的日志文件。 |
- | void log(String message, Throwable throwable) | 将消息和异常信息写入 Servlet 容器的日志文件。 |
获取容器信息 | String getServerInfo() | 返回 Servlet 容器的名称和版本信息。 |
- | int getMajorVersion() | 返回 Servlet API 的主版本号。 |
- | int getMinorVersion() | 返回 Servlet API 的次版本号。 |
其他方法 | String getContextPath() | 返回 Web 应用的上下文路径(例如 /myapp )。 |
- | String getMimeType(String file) | 返回指定文件的 MIME 类型(例如 text/html 或 image/jpeg )。 |
- | RequestDispatcher getRequestDispatcher(String path) | 返回一个 RequestDispatcher 对象,用于请求转发或包含其他资源。 |
使用示例
以下是一些常见的使用场景和示例:
(1) 获取初始化参数
在 web.xml
中配置上下文参数:
<context-param><param-name>appName</param-name><param-value>My Web Application</param-value>
</context-param>
在 Servlet 中获取参数:
String appName = getServletContext().getInitParameter("appName");
System.out.println("Application Name: " + appName);
(2) 获取资源
读取 WEB-INF
目录下的配置文件:
InputStream inputStream = getServletContext().getResourceAsStream("/WEB-INF/config.properties");
Properties properties = new Properties();
properties.load(inputStream);
String value = properties.getProperty("key");
(3) 共享数据
设置应用范围内的属性:
getServletContext().setAttribute("userCount", 100);
获取应用范围内的属性:
int userCount = (Integer) getServletContext().getAttribute("userCount");
(4) 记录日志
记录日志信息:
getServletContext().log("An error occurred in the application.");
GenericServlet与Servlet是什么关系
实现 ServletConfig 和 Servlet 接口 | GenericServlet 实现了 Servlet 和 ServletConfig 接口,并提供了一些默认的方法实现。 |
---|---|
简化 Servlet 开发 | 开发者可以通过继承 GenericServlet 来创建自定义的 Servlet,而不需要实现所有 Servlet 接口的方法。 |
注意事项 | GenericServlet 没有提供 service 方法的默认实现,开发者必须重写此方法。 |
- | 可以通过重写无参的 init() 方法来实现自定义的初始化逻辑,而不需要直接处理 ServletConfig 对象。 |
GenericServlet的核心方法有哪些
方法 | 介绍 | |
---|---|---|
Servlet 生命周期方法 | void init(ServletConfig config) | 初始化 Servlet。GenericServlet 提供了默认实现,将 ServletConfig 对象保存起来,并调用无参的 init() 方法。 |
- | void init() | 无参的初始化方法,开发者可以重写此方法来实现自定义的初始化逻辑。 |
- | void service(ServletRequest req, ServletResponse res) | 处理客户端请求的核心方法。GenericServlet 没有提供默认实现,开发者必须重写此方法。 |
- | void destroy() | 销毁 Servlet。GenericServlet 提供了默认实现,开发者可以重写此方法来实现自定义的销毁逻辑。 |
获取配置信息 | ServletConfig getServletConfig() | 返回 ServletConfig 对象。 |
- | String getInitParameter(String name) | 根据参数名称获取 Servlet 的初始化参数值。 |
- | Enumeration<String> getInitParameterNames() | 返回所有初始化参数的名称。 |
- | ServletContext getServletContext() | 返回 ServletContext 对象。 |
日志 | void log(String msg) | 将消息写入 Servlet 容器的日志文件。 |
- | void log(String msg, Throwable t) | 将消息和异常信息写入 Servlet 容器的日志文件。 |
其它方法 | String getServletInfo() | 返回 Servlet 的描述信息。默认返回空字符串,开发者可以重写此方法。 |
- | String getServletName() | 返回 Servlet 的名称。 |
使用示例
以下是一个简单的示例,展示如何通过继承 GenericServlet
创建自定义的 Servlet:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;public class MyServlet extends GenericServlet {@Overridepublic void init() throws ServletException {// 自定义初始化逻辑System.out.println("Servlet initialized.");}@Overridepublic void service(ServletRequest req, ServletResponse res)throws ServletException, IOException {// 设置响应内容类型res.setContentType("text/html;charset=UTF-8");// 获取输出流PrintWriter out = res.getWriter();// 向客户端发送响应out.println("<html>");out.println("<head><title>MyServlet</title></head>");out.println("<body>");out.println("<h1>Hello, World!</h1>");out.println("</body>");out.println("</html>");}@Overridepublic void destroy() {// 自定义销毁逻辑System.out.println("Servlet destroyed.");}
}
GenericServlet
与 HttpServlet
的区别是什么
区别 | GenericServlet | HttpServlet |
---|---|---|
父子类 | - | GenericServlet 的子类。 |
协议无关性 | 适用于任何协议,包括HTTP、FTP等。 | 专用于 HTTP 协议。提供了对 HTTP 方法的支持(如:doGet、doPost)。 |
相关文章:
Java Web 之 Servlet 100问
Filter 是什么? 在Java Web开发中,Filter(过滤器)是一种用于在请求到达目标资源(如Servlet、JSP)之前或响应返回客户端之前进行预处理和后处理的组件。Filter可以拦截请求和响应,执行特定的操作…...
z-library电子图书馆最新地址的查询方法
对于喜欢读书的伙伴们,应该都听说过z站(z-library),优点多多,缺点就是地址不稳定,经常会变化网站地址。然后我最近发现了一个工具,可以不间断更新官方可用的z站地址:电子书最新地址...
PyCharm入门导览
一、项目视图 项目视图位置如下所示: 项目视图是主要工具窗口之一。它包含项目目录、SDK特定的外部库和临时文件。点击带条纹的按 钮可以预览演示项目。也可以按Alt 1 打开。 二、Python解释器 点击右下角项目的名字,可以快速进入【Python解释器】界面…...
算法题(127):最大子段和
审题: 本题需要我们找到n个整数中连续且非空的最大子段和 思路: 方法一:前缀和 我们的思路是将每个索引位置的最大子段和求出,然后用answer进行max维护,最后输出answer即可 最大子段和怎么求? 子段和 f[i]…...
物联网分层架构全解析:从感知到应用的智能生态构建
物联网分层架构一般可细分为感知层、网络层、平台层和应用层,以下是各层更详细的介绍: 一、感知层 1.功能 数据采集:利用各类传感器对物理世界的各种信息进行采集,包括环境参数(如温度、湿度、光照、气压等…...
系统架构师2025年论文通用模板
搭建自己的模板 1、项目选择与实施建议整理 一、项目选择标准 金额与周期要求:优先选择金额在 200万以上 的中大型商业项目,研发周期建议 不少于8个月。避免选择小型项目(如金额低于100万、周期短于1年)。 …...
Flink 2.0 编译
文章目录 Flink 2.0 编译第一个问题 java 版本太低maven 版本太低maven 版本太高开始编译扩展多版本jdk 配置 Flink 2.0 编译 看到Flink2.0 出来了,想去玩玩,看看怎么样,当然第一件事,就是编译代码,但是没想到这么多问…...
Java线程的几种状态
线程状态我们在此介绍六种线程状态 1.NEW 2.RUNNABLE 3.TIMED_WAITING 4.BLOCKED 5.WAITING 6.TERMINATED 1.初始状态 (NEW) 当一个线程对象被创建但尚未调用 start() 方法时,线程处于初始状态。此时,线程还没有开始执行。 通俗的讲就是安排了工作但是…...
2025年03月中国电子学会青少年软件编程(Python)等级考试试卷(一级)真题
青少年软件编程(Python)等级考试试卷(一级) 分数:100 题数:37 答案解析:https://blog.csdn.net/qq_33897084/article/details/147335019?spm1001.2014.3001.5501 一、单选题(共25题࿰…...
「数据可视化 D3系列」入门第十章:饼图绘制详解与实现
饼图绘制详解与实现 一、饼图绘制核心知识1. d3.arc() 弧形生成器2. d3.pie() 布局函数3. arc.centroid() 中心点计算4. 颜色方案 二、饼图实现代码小结核心知识点下章预告:力导向图 一、饼图绘制核心知识 1. d3.arc() 弧形生成器 功能: 生成圆形、扇形…...
三维点拟合平面ransac c++
理论 平面的一般定义 在三维空间中,一个平面可以由两个要素唯一确定: 法向量 n(a,b,c):垂直于平面的方向 平面上一点 平面上任意一点 p(x,y,z) 满足: ( p − p 0 ) ∗ n 0 (p - p0) * n 0 (p−p0)∗n0 即 a ( x − x 0 ) …...
第六章:6.6输入以下的杨辉三角形,要求输出10行
//输入以下的杨辉三角形,要求输出10行 #include<stdio.h> int main() {int a[10][10] { 0 };int i 0, j 0;for (i 0; i < 10; i){for (j 0; j < 10; j){if (j 0){a[i][j] 1;}else if (i j){a[i][j] 1;}else{a[i][j] a[i - 1][j - 1] a[i - …...
初识Redis · C++客户端string
目录 前言: string的API使用 set get: expire: NX XX: mset,mget: getrange setrange: incr decr 前言: 在前文,我们已经学习了Redis的定制化客户端怎么来的,以及如何配置好Redis定制化客户端&…...
React 事件处理基础
React 中最常见的两个需求,一个是列表渲染,另一个就是绑定点击事件。 这一篇就是从最基础的按钮点击开始,分四个阶段,逐步理解 React 中事件的写法和参数传递方式。 📍阶段一:最简单的点击事件 function A…...
插入排序和希尔排序
今天给小伙伴们分享两个比较基础的排序算法,插入排序和希尔排序,这两个排序算法之间联系还是挺多的,所以放在一起。希尔排序可以看作是插入排序的升级版,在面对一些更为复杂的场景时,希尔排序的效率往往要比插入排序高…...
Model Context Protocol (MCP) 开放协议对医疗多模态数据整合的分析路径【附代码】
Model Context Protocol (MCP) 作为一种革命性的开放协议,正在重塑医疗领域多模态数据整合的方式。本文将深入分析MCP协议在医疗多模态数据整合中的具体路径、技术实现、应用场景及未来发展方向,揭示这一协议如何成为连接AI与医疗数据的关键桥梁。 MCP协议概述及其在医疗多模…...
Oracle 11g通过dg4odbc配置dblink连接PostgreSQL
1、安装unixodbc 2、安装postgresql yum install -y postgresql17-odbc 3、配置postgresqlodbc数据源 vim /usr/local/etc/odbcinst.ini##添加如下 [mypg] Driver /usr/lib64/psqlodbcw.so Servername localhost Port 5432 Database postgres Username postgres Pas…...
docker 安装prometheus普罗米修斯
prometheus(普罗米修斯):天生为采集存储监控数据而生的时序数据库。prometheus通过各种Exporter采集到监控数据,然后存储进prometheus中,以供查询展示 grafana:一个监控仪表系统。grafana的数据来源可以有…...
Ubuntu上安装Mysql
步骤 1:安装 MySQL Server sudo apt update sudo apt install mysql-server -y这将安装最新版本的 MySQL 8.0 以及所有依赖组件。 步骤 2:检查安装是否成功 mysql --version sudo systemctl status mysql如果状态是 active (running),说明成…...
Spring Boot启动流程深度解析:从main()到应用就绪的完整旅程
🌱 Spring Boot启动流程深度解析:从main()到应用就绪的完整旅程 #SpringBoot核心 #启动原理 #自动配置 #源码解析 一、启动流程图解 (1) 启动类执行 → (2) SpringApplication初始化 → (3) 事件驱动模型启动 ↓ …...
2025TGCTF Web WP复现
AAA 偷渡阴平 <?php$tgctf2025$_GET[tgctf2025];if(!preg_match("/0|1|[3-9]|\~|\|\|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\|\|\{|\[|\]|\}|\:|\|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $tgctf2025)){//hint:你可以对着键盘…...
交叉注意力层的实质作用:连接编码器和解码器
交叉注意力层的实质作用 在Transformer架构里,交叉注意力层主要作用是连接编码器和解码器,让解码器能够利用编码器输出的上下文信息 。具体来说: 聚焦相关信息:以机器翻译任务为例,在将源语言句子翻译成目标语言时,交叉注意力能使解码器生成的每个词,都聚焦于源语言序列…...
conversation_template | conversation_actors | conversation_line_template
目录 conversation_template conversation_actors conversation_line_template 实例应用 conversation_template id:某段谈话的唯一编号FirstLineId:谈话开始的第一段话的编号,取值来源 ConversationLine.db2 的 ID 字段TextureKitId&am…...
C++ `shared_ptr` 多线程使用
C shared_ptr 多线程使用 一、核心结论 引用计数:shared_ptr 的引用计数操作是原子的,线程安全控制块修改:修改 shared_ptr 指向的对象需要同步被管理对象:若对象本身非线程安全,访问时仍需加锁 二、分场景详解 场景…...
十天借助 Trae 实现 “幸运塔塔屋” 小程序时光记忆功能之旅
在软件开发的广阔天地中,创新与效率始终是开发者们不懈追求的目标。近期,我成功完成了一次极具挑战性与创新性的实践 —— 仅用十天时间,借助 Trae 这款强大的 AI 工具,开发出了 “幸运塔塔屋” 小程序,其中的 “时光记…...
WiFi“管家”------hostapd的工作流程
目录 1. 启动与初始化 1.1 解析命令行参数 1.2 读取配置文件 1.3 创建接口和 BSS 数据结构 1.4 初始化驱动程序 2. 认证和关联处理 2.1 监听认证请求 2.2 处理认证请求 2.3 处理关联请求 3. 数据转发 3.1 接收客户端数据 3.2 转发数据 4. 断开连接处理 4.1 处理客…...
计算机视觉——基于使用 OpenCV 与 Python 实现相机标定畸变校正
概述 相机标定是一种旨在通过确定相机的内参(焦距、光学中心、畸变系数)和外参(相机的位置和方向),提高图像在现实世界中的几何精度的过程。该过程可以纠正相机拍摄的图像中的畸变,使相机能够准确感知现实…...
OOM 未触发 JVM 崩溃的可能原因
1. OOM 未触发 JVM 崩溃的可能原因 (1) 未配置 JVM 参数强制崩溃 关键参数缺失: 若未添加 -XX:CrashOnOutOfMemoryError,JVM 在 OOM 时可能仅抛出异常并正常退出,而非崩溃,因此不会生成 hs_err_pid.log。 # 正确配置示例&…...
计算机视觉cv2入门之车牌号码识别
前边我们已经讲解了使用cv2进行图像预处理与边缘检测等方面的知识,这里我们以车牌号码识别这一案例来实操一下。 大致思路 车牌号码识别的大致流程可以分为这三步:图像预处理-寻找车牌轮廓-车牌OCR识别 接下来我们按照这三步来进行讲解。 图像预处理 …...
xml+html 概述
1.什么是xml xml 是可扩展标记语言的缩写: Extensible Markup Language。 <root><h1> text 1</h1> </root> web 应用开发,需要配置 web.xml,就是个典型的 xml文件 <web-app><servlet><servlet-name&…...
C++数据结构与二叉树详解
前言: 在C编程的世界里,数据结构是构建高效程序的基石,而二叉树则是其中最优雅且应用广泛的数据结构之一。本文将带你深入理解二叉树的本质、实现与应用,助你在算法设计中游刃有余。 一、二叉树的基本概念 1. 什么是二叉树 二叉树…...
解决6栈6层码头集装箱堆栈翻箱最优解问题
‘’’ con 1 origin_stack = [ [4, 4, 1, 0, 0, 0], # 第一栈 [4, 3, 2, 1, 0, 0], # 第二栈 [4, 2, 2, 1, 0, 0], # 第三栈 [3, 3, 3, 1, 0, 0], # 第四栈 [3, 4, 2, 1, 0, 0], # 第五栈 [4, 2, 3, 2, 0, 0] # 第六栈 ] con 2 origin_stack = [ [4, 4, 3, 0, 0, 0], # 第一栈…...
Java 序列化与反序列化终极解析
Java 序列化与反序列化终极解析 1. 核心概念 (1) 什么是序列化? 定义:将对象转换为字节流的过程(对象 → 字节) 目的: 持久化存储(如保存到文件) 网络传输(如RPC调用)…...
YOLOv5、YOLOv6、YOLOv7、YOLOv8、YOLOv9、YOLOv10、YOLOv11、YOLOv12的网络结构图
文章目录 一、YOLOv5二、YOLOv6三、YOLOv7四、YOLOv8五、YOLOv9六、YOLOv10七、YOLOv11八、YOLOv12九、目标检测系列文章 本文将给出YOLO各版本(YOLOv5、YOLOv6、YOLOv7、YOLOv8、YOLOv9、YOLOv10、YOLOv11、YOLOv12)网络结构图的绘制方法及图。本文所展…...
leetcode0145. 二叉树的后序遍历-easy
1 题目:二叉树的后序遍历 官方标定难度:易 给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。 示例 1: 输入:root [1,null,2,3] 输出:[3,2,1] 解释: 示例 2: 输入…...
【Leetcode 每日一题】2364. 统计坏数对的数目
问题背景 给你一个下标从 0 0 0 开始的整数数组 n u m s nums nums。如果 i < j i < j i<j 且 j − i ≠ n u m s [ j ] − n u m s [ i ] j - i \ne nums[j] - nums[i] j−inums[j]−nums[i],那么我们称 ( i , j ) (i, j) (i,j) 是一个 坏数对 。…...
完整的 .NET 6 分布式定时任务实现(Hangfire + Redis 分布式锁)
完整的 .NET 6 分布式定时任务实现(Hangfire Redis 分布式锁) 以下是完整的解决方案,包含所有必要组件: 1. 基础设施层 1.1 分布式锁服务 // IDistributedLockService.cs public interface IDistributedLockService {ValueTa…...
人脸识别联合行为检测的办公管理新模式
基于人脸识别与行为检测的办公智能化解决方案 一、背景 在传统办公场景中,员工考勤管理、工位使用情况统计、安全监控等环节存在诸多痛点。例如,传统考勤方式如指纹打卡、刷卡等存在代打卡现象,考勤数据不准确;对于员工是否在工…...
鸿蒙NEXT开发键盘工具类(ArkTs)
export declare type KeyboardCallBack (show: boolean, height: number) > void; import { AppUtil } from ./AppUtil; import { LogUtil } from ./LogUtil; import { ArrayUtil } from ./ArrayUtil;/*** 键盘工具类* author 鸿蒙布道师* since 2025/04/18*/ export class…...
Python爬虫第17节-动态渲染页面抓取之Selenium使用下篇
目录 引言 一、获取节点信息 1.1 获取属性 1.2 获取文本值 1.3 获取ID、位置、标签名、大小 二、切换Frame 三、延时等待 3.1 隐式等待 3.2 显式等待 四、前进后退 五、Cookies 六、选项卡管理 七、异常处理 引言 这一节我们继续讲解Selenium的使用下篇࿰…...
【数据结构】第四弹——LinkedList与链表
文章目录 一. ArrayList 的缺陷二.链表2.1 链表的概念及结构2.2 链表的结构2.2.1 单向或者双向2.2.2 带头或者不带头2.2.3 循环非循环 2.3 链表的实现1. IList接口2. MySingleList 类中具体实现(不带头单向非循环链表)1. 节点抽象成内部类手搓一个链表2. 头插法3. 尾插法4. 指定…...
设计模式从入门到精通之(五)观察者模式
观察者模式:实现高效事件通知的秘诀 在日常生活中,我们经常需要同步通知多方的信息变更。比如天气预报系统、股票价格波动提醒、社交媒体的点赞通知等。这些场景中,通知机制需要高效、灵活,而不会因为通知方的变化影响系统整体。 …...
chili3d调试笔记3 加入c++ 大模型对话方法 cmakelists精读
加入 #include <emscripten/bind.h> #include <emscripten/val.h> #include <nlohmann/json.hpp> 怎么加包 函数直接用emscripten::function,如: emscripten::function("send_to_llm", &send_to_llm); set (CMAKE_C…...
使用人工智能大模型kimi,如何免费制作PPT?
使用人工智能大模型kimi,如何免费制作PPT? 手把手操作视频https://edu.csdn.net/learn/40406/666573...
ModbusTCP 转 Profinet 主站网关
一、 功能概述 1.1 设备简介 本产品是 ModbusTCP 和 Profinet(M) 网关(以下简称网关),使用数据映射 方式工作。 本产品在 ModbusTCP 侧作为 ModbusTCP 从站,接 PLC 、上位机、 wincc 屏 等;在 Profin…...
进阶篇|CAN FD 与性能优化
引言 1. CAN vs. CAN FD 对比 2. CAN FD 帧结构详解...
6.6 “3步调用ChatGPT打造高可靠Python调度器,零依赖实现定时任务自动化“
3步调用ChatGPT打造高可靠Python调度器,零依赖实现定时任务自动化 关键词:ChatGPT代码生成、Python调度器设计、定时任务自动化、异常处理机制、日志监控系统 需求分析与技术选型 GitHub Sentinel 需要实现两种定时任务模式: #mermaid-svg-prOScv2NNhn6w90N {font-family:…...
HarmonyOS 基础语法概述 UI范式
ArkUI框架 - UI范式 ArkTS的基本组成 装饰器: 用于装饰类、结构、方法以及变量,并赋予其特殊的含义。如上述示例中Entry、Component和State都是装饰器,Component表示自定义组件,Entry表示该自定义组件为入口组件,Stat…...
23种设计模式-创建型模式之建造者模式(Java版本)
Java 建造者模式(Builder Pattern)详解 🧱 什么是建造者模式? 建造者模式用于将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。 适用于创建过程复杂、构造顺序稳定但组件变化的对象。…...
【AI提示词】退休规划顾问专家
提示说明 随着人口老龄化的加剧,越来越多的人开始关注退休规划问题。一个专业的退休规划顾问可以帮助用户合理规划退休生活,确保退休后的生活质量。 提示词 # 角色 退休规划顾问专家## 注意 1. 专家设计应符合退休规划的专业性和可靠性,帮…...