0%

Windows 中查看端口占用并结束进程的方法

在开发或运维过程中,经常会遇到 “端口被占用” 的问题(如启动服务时提示 “Address already in use”)。以下是通过 CMD 命令行快速定位端口占用进程并结束它的完整步骤:

查看指定端口被哪个进程占用

  1. 打开 CMD 命令行
    按下Win + R,输入cmd,回车打开命令提示符(无需管理员权限)。

  2. 执行端口查询命令
    使用netstat命令结合findstr筛选目标端口,语法如下:

    1
    netstat -ano | findstr "端口号"
    • netstat -ano:列出所有网络连接(-a)、显示端口号(-n)、显示进程 ID(-o)。
    • findstr "端口号":从结果中筛选包含目标端口的记录。

    示例:查询 8990 端口的占用情况

    1
    netstat -ano | findstr "8990"
  3. 解析结果
    输出格式为:协议 本地地址:端口 外部地址 状态 进程ID(PID)
    例如:

    1
    TCP    127.0.0.1:8990         0.0.0.0:0              LISTENING       2700

    说明:8990 端口被进程 ID 为 2700的程序占用,状态为 “LISTENING”(监听中)。

根据进程 ID 查询进程名称

通过第一步获取的进程 ID(PID),可以进一步找到对应的程序名称:

阅读全文 »

单元测试中数据库数据未更新的问题解析:自动回滚机制与解决方案

在进行单元测试(尤其是涉及数据库操作的测试)时,常遇到 “测试执行成功但数据库数据未变化” 的现象。这通常与测试框架的事务自动回滚机制有关,本文将解析其原理并提供解决方案。

问题根源:测试框架的自动回滚机制

主流的 Java 测试框架(如 Spring Test)为了避免测试数据污染数据库,默认会对测试方法中的数据库操作进行自动回滚。其核心逻辑是:

  1. 测试方法执行前,框架开启一个事务;
  2. 测试方法中的数据库操作(如插入、更新)在该事务中执行;
  3. 测试方法执行成功后,框架自动回滚事务,所有操作不提交到数据库;
  4. 若测试失败,同样会回滚事务,保证数据库状态不受影响。

这一机制的优点是隔离测试数据,避免多次测试之间的相互干扰,但也会导致 “测试成功却看不到数据变化” 的现象。

解决方案:禁用自动回滚

若需要在测试后保留数据库数据(如验证数据正确性、调试测试逻辑),可通过以下方式禁用自动回滚:

使用 @Rollback 注解(Spring Test)

在测试方法或测试类上添加 @Rollback(false),显式关闭自动回滚:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringRunner.class)
@Transactional // 开启事务(默认会回滚)
public class UserDaoTest {

@Test
@Rollback(false) // 禁用自动回滚,测试完成后提交事务
public void testInsertUser() {
// 数据库插入操作(如 userDao.insert(new User("test")))
// 测试成功后,数据会保留在数据库中
}
}
阅读全文 »

Java Web 中文乱码问题全解析:GET/POST 请求编码解决方案

中文乱码是 Java Web 开发中常见的问题,根源在于请求参数编码与解码方式不匹配。GET 和 POST 请求的参数传递方式不同,乱码原因和解决方案也存在差异。本文将详细分析中文乱码的成因,并提供针对性的解决方法,覆盖 Tomcat 配置、代码处理等多种场景。

中文乱码的本质原因

HTTP 协议默认使用 ISO-8859-1 编码(不支持中文),若客户端发送的中文参数使用 UTF-8 编码,而服务器端用 ISO-8859-1 解码,就会导致乱码(表现为 ??? 或一串无意义字符)。

  • GET 请求:参数附加在 URL 中,编码由服务器的 URI 编码配置决定;
  • POST 请求:参数放在请求体中,编码由 Content-Type 头的 charset 指定,若未指定则默认使用 ISO-8859-1。

GET 请求中文乱码解决方案

GET 请求参数通过 URL 传递,其编码处理依赖服务器配置(如 Tomcat 的 URI 编码设置),常见解决方案如下:

方案一:修改 Tomcat 配置(推荐)

在 Tomcat 的 conf/server.xml 中,为 Connector 节点添加 URIEncoding="UTF-8" 属性,强制服务器对 URI 中的参数使用 UTF-8 解码:

1
2
3
4
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8" /> <!-- 添加此行 -->
  • 作用:所有 GET 请求的 URL 参数均使用 UTF-8 解码,一劳永逸解决乱码;
  • 适用场景:有权限修改服务器配置的环境(如开发、测试环境)。

方案二:使用请求体编码同步 URI 编码

若无法修改 Tomcat 配置,可在 Connector 中添加 useBodyEncodingForURI="true",使 URI 编码与请求体编码保持一致:

阅读全文 »

Java Web 中多个请求共享同一个 Servlet 的实现方案

在 Java Web 开发中,多个请求共用同一个 Servlet 是常见需求(如一个模块的增删改查操作)。这种方式可避免创建过多 Servlet 类,简化代码结构。本文将详细介绍两种主流实现方案:基于请求参数的方法分发和基于 URL 路径的反射调用。

方案一:基于请求参数的方法分发

通过在 URL 中添加 method 参数(如 ?method=add?method=delete),在 Servlet 中根据参数值分发到不同处理方法。

实现步骤:

  1. 前端请求携带 method 参数
1
2
3
4
5
6
7
8
<!-- 列表页面 -->
<a href="/user?method=list">用户列表</a>
<!-- 添加页面 -->
<a href="/user?method=toAdd">添加用户</a>
<!-- 表单提交 -->
<form action="/user?method=save" method="post">
<!-- 表单内容 -->
</form>
  1. Servlet 中根据 method 分发处理
阅读全文 »

POST 请求体无法重复读取的原因与解决方案

在 Java Web 开发中,经常会遇到 “POST 请求体只能读取一次” 的问题:当过滤器(Filter)读取请求体后,Servlet 中再次读取时会返回空数据。这一现象与请求流的底层实现密切相关,本文将解析其原因,并提供基于请求包装类的解决方案。

为什么 POST 请求体无法重复读取?

POST 请求体的内容通过输入流(ServletInputStream)读取,而输入流具有一次性读取的特性,核心原因如下:

1. 输入流的 “消费性”

输入流(如 CoyoteInputStream,Tomcat 的实现)本质上是对底层字节流的封装,其读取过程是 “消费性” 的:

  • 读取数据时,流的指针会向后移动;
  • 当流读取完毕(指针到达末尾),再次读取会返回 -1(表示已读完);
  • 流关闭后(如 close() 被调用),无法再次打开或重置。

2. Tomcat 中的具体实现

以 Tomcat 为例,getInputStream() 返回的 CoyoteInputStream 内部依赖 InputBuffer 存储请求体数据。当数据被读取后,InputBuffer 中的缓存会被清空,且流的 closed 状态会被标记为 true

1
2
3
4
5
6
7
8
9
10
11
12
13
// Tomcat 的 CoyoteInputStream 部分源码
public int read(byte[] b, int off, int len) throws IOException {
if (closed) { // 若流已关闭,直接抛出异常
throw new IOException("Stream closed");
}
if (checkByteBufferEof()) { // 若数据已读完,返回 -1
return -1;
}
// 读取剩余数据并移动指针
int n = Math.min(len, bb.remaining());
bb.get(b, off, n);
return n;
}
阅读全文 »