外观
JavaWeb 笔记
约 2758 字大约 9 分钟
2025-08-16
一、Java Web 简介
1.1 什么是 Java Web?
Java Web 指的是使用 Java 技术开发的 Web 应用程序。Java Web 应用程序通常由前端和后端组成,具有以下特点:
- 可移植性高:基于 JVM,一次编写,到处运行
- 安全性好:Java 语言本身的安全机制和 Web 容器的安全控制
- 性能稳定:成熟的框架和优化的 JVM
- 开源社区活跃:丰富的开源框架和工具
1.2 Java Web 技术栈
现代 Java Web 开发主要技术栈:
- 核心:Servlet API、JSP(逐渐被替代)
- 主流框架:Spring Boot、Spring MVC、MyBatis
- 数据库:MySQL、Oracle、PostgreSQL
- 构建工具:Maven、Gradle
- 前端技术:HTML/CSS/JavaScript、Vue/React/Angular
二、Servlet 核心技术
2.1 Servlet 基础
Servlet 是 Java Web 的核心组件,用于处理客户端请求并生成响应。
Servlet 生命周期:
- 加载和实例化:容器创建 Servlet 实例
- 初始化:调用
init()方法 - 处理请求:调用
service()方法(根据请求类型调用 doGet() 或 doPost()) - 销毁:调用
destroy()方法,释放资源
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class HelloWorldServlet extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("Servlet 初始化");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>Hello World!</h1>");
out.println("</body></html>");
}
@Override
public void destroy() {
System.out.println("Servlet 销毁");
}
}2.2 Servlet 配置
web.xml 配置(传统方式):
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.example.HelloWorldServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>注解配置(Servlet 3.0+,推荐):
@WebServlet("/hello")
public class HelloWorldServlet extends HttpServlet {
// Servlet 代码
}2.3 请求与响应
请求处理
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取请求参数
String username = request.getParameter("username");
String[] hobbies = request.getParameterValues("hobby");
// 获取请求头
String userAgent = request.getHeader("User-Agent");
// 获取请求方法
String method = request.getMethod();
// 获取会话
HttpSession session = request.getSession();
// 获取上下文
ServletContext context = getServletContext();
}响应处理
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应类型
response.setContentType("text/html;charset=UTF-8");
// 设置响应状态码
response.setStatus(HttpServletResponse.SC_OK);
// 重定向
// response.sendRedirect("newPage");
// 转发请求
// request.getRequestDispatcher("newPage.jsp").forward(request, response);
// 写入响应内容
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>提交成功</h1>");
out.println("</body></html>");
}2.4 域对象与数据共享
| 对象 | 创建 | 销毁 | 范围 | 常用场景 |
|---|---|---|---|---|
| ServletContext | 服务器启动,项目加载时 | 服务器关闭或项目卸载时 | 整个 web 项目 | 全局配置、应用级数据 |
| HttpSession | 用户第一次调用 request.getSession() 时 | 服务器非正常关闭、未活跃状态 30 分钟、主动销毁 | 一次会话中,多次请求间 | 用户登录状态、购物车 |
| HttpServletRequest | 用户发送请求时 | 服务器做出响应后 | 一次请求中,多次转发间 | 请求处理结果传递 |
使用示例:
// ServletContext (应用域)
getServletContext().setAttribute("appConfig", config);
String config = (String)getServletContext().getAttribute("appConfig");
// HttpSession (会话域)
HttpSession session = request.getSession();
session.setAttribute("user", user);
User user = (User)session.getAttribute("user");
// HttpServletRequest (请求域)
request.setAttribute("result", result);
RequestDispatcher dispatcher = request.getRequestDispatcher("result.jsp");
dispatcher.forward(request, response);2.5 Servlet 过滤器
过滤器用于在请求到达 Servlet 前或响应返回客户端前进行预处理。
@WebFilter("/*")
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化代码
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
// 请求前处理
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 继续执行后续过滤器或目标资源
chain.doFilter(request, response);
// 响应后处理
}
@Override
public void destroy() {
// 资源清理
}
}常用过滤器场景:
- 字符编码处理
- 身份验证和授权
- 日志记录
- 敏感词过滤
- 压缩响应内容
三、MVC 设计模式
3.1 MVC 概述
MVC(Model-View-Controller)是一种软件设计模式,将应用程序分解为三个核心组件:
- 模型(Model):负责管理应用程序的数据和业务逻辑
- 视图(View):负责显示用户界面(通常使用 JSP、Thymeleaf 或前端框架)
- 控制器(Controller):处理用户输入,协调模型和视图

3.2 MVC 优势
- 分离关注点:各组件职责明确,提高代码可读性和可维护性
- 代码复用:模型可以在多个视图中复用
- 并行开发:前端和后端可以并行开发
- 易于测试:各组件可以独立测试
3.3 Spring MVC 实现
Spring MVC 是 Java Web 中最流行的 MVC 框架。
控制器示例:
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
// 获取所有用户
@GetMapping
public List<User> getAllUsers() {
return userService.findAll();
}
// 根据ID获取用户
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
return userService.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
// 创建新用户
@PostMapping
public User createUser(@RequestBody User user) {
return userService.save(user);
}
// 更新用户
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User userDetails) {
return userService.findById(id)
.map(user -> {
user.setName(userDetails.getName());
user.setEmail(userDetails.getEmail());
User updatedUser = userService.save(user);
return ResponseEntity.ok().body(updatedUser);
})
.orElse(ResponseEntity.notFound().build());
}
// 删除用户
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
if (!userService.existsById(id)) {
return ResponseEntity.notFound().build();
}
userService.deleteById(id);
return ResponseEntity.noContent().build();
}
}四、数据库操作(JDBC 与 ORM)
4.1 JDBC 基础
JDBC(Java Database Connectivity)是 Java 访问数据库的标准 API。
JDBC 操作步骤:
- 加载数据库驱动
- 建立数据库连接
- 创建 Statement 对象
- 执行 SQL 语句
- 处理结果集
- 关闭资源
public class JdbcDemo {
private static final String URL = "jdbc:mysql://localhost:3306/mydb";
private static final String USER = "root";
private static final String PASSWORD = "123456";
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 1. 加载驱动(JDBC 4.0+ 可省略)
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 获取连接
conn = DriverManager.getConnection(URL, USER, PASSWORD);
// 3. 创建 Statement
stmt = conn.createStatement();
// 4. 执行查询
rs = stmt.executeQuery("SELECT * FROM users");
// 5. 处理结果
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
System.out.println(id + ", " + name + ", " + email);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 6. 关闭资源
try {
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}4.2 连接池(推荐使用)
直接使用 JDBC 会频繁创建和销毁连接,效率低下。推荐使用连接池:
HikariCP 配置示例:
// 创建 HikariCP 连接池
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("root");
config.setPassword("123456");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
HikariDataSource dataSource = new HikariDataSource(config);
// 从连接池获取连接
try (Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {
// 处理结果集
} catch (SQLException e) {
e.printStackTrace();
}4.3 ORM 框架(MyBatis)
MyBatis 是轻量级的 ORM 框架,简化数据库操作。
MyBatis 配置:
<!-- mybatis-config.xml -->
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>Mapper XML 文件:
<!-- UserMapper.xml -->
<mapper namespace="com.example.mapper.UserMapper">
<select id="selectUser" resultType="com.example.model.User">
SELECT * FROM users WHERE id = #{id}
</select>
<insert id="insertUser" parameterType="com.example.model.User">
INSERT INTO users(name, email) VALUES(#{name}, #{email})
</insert>
<update id="updateUser" parameterType="com.example.model.User">
UPDATE users SET name=#{name}, email=#{email} WHERE id=#{id}
</update>
<delete id="deleteUser" parameterType="int">
DELETE FROM users WHERE id=#{id}
</delete>
</mapper>Java 代码调用:
// 初始化 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 执行数据库操作
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
// 查询
User user = mapper.selectUser(1);
// 插入
User newUser = new User("张三", "zhangsan@example.com");
mapper.insertUser(newUser);
session.commit(); // 提交事务
}五、RESTful API 设计
5.1 RESTful 基本原则
- 资源导向:将系统功能抽象为资源
- 统一接口:使用标准 HTTP 方法操作资源
- 无状态:每个请求包含所有必要信息
- 可缓存:响应应明确是否可缓存
- 分层系统:客户端无需知道与服务器的交互是否通过中间层
5.2 HTTP 方法与资源操作
| HTTP 方法 | 资源操作 | 幂等性 | 安全性 |
|---|---|---|---|
| GET | 查询 | 是 | 是 |
| POST | 创建 | 否 | 否 |
| PUT | 全量更新 | 是 | 否 |
| PATCH | 部分更新 | 否 | 否 |
| DELETE | 删除 | 是 | 否 |
5.3 RESTful API 设计规范
资源命名:
- 使用名词复数表示资源集合
- 使用连字符
-代替下划线_ - 保持小写
/api/users /api/orders资源操作:
GET /api/users # 获取用户列表 POST /api/users # 创建新用户 GET /api/users/{id} # 获取指定用户 PUT /api/users/{id} # 全量更新用户 PATCH /api/users/{id} # 部分更新用户 DELETE /api/users/{id} # 删除用户版本控制:
- URL 路径:
/api/v1/users - 请求头:
Accept: application/vnd.example.v1+json
- URL 路径:
状态码:
- 200 OK:成功
- 201 Created:资源创建成功
- 204 No Content:操作成功但无内容返回
- 400 Bad Request:客户端错误
- 401 Unauthorized:未认证
- 403 Forbidden:无权限
- 404 Not Found:资源不存在
- 500 Internal Server Error:服务器错误
分页、排序和过滤:
GET /api/users?page=2&size=10&sort=name,asc&email=example.com
5.4 Spring Boot 实现 RESTful API
@RestController
@RequestMapping("/api/v1/users")
public class UserRestController {
@Autowired
private UserService userService;
// 分页查询用户
@GetMapping
public ResponseEntity<Page<User>> getAllUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(defaultValue = "id,asc") String sort) {
Sort.Direction direction = sort.contains(",desc") ? Sort.Direction.DESC : Sort.Direction.ASC;
String property = sort.replace(",asc", "").replace(",desc", "");
Pageable pageable = PageRequest.of(page, size, Sort.by(direction, property));
Page<User> users = userService.findAll(pageable);
return ResponseEntity.ok(users);
}
// 创建用户
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
User savedUser = userService.save(user);
URI location = ServletUriComponentsBuilder
.fromCurrentRequest()
.path("/{id}")
.buildAndExpand(savedUser.getId())
.toUri();
return ResponseEntity.created(location).body(savedUser);
}
// 全局异常处理
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleValidationExceptions(
MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage()));
return ResponseEntity.badRequest().body(errors);
}
}六、Java Web 安全
6.1 身份认证与授权
Spring Security 配置:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/public/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
.and()
.httpBasic();
}
}6.2 HTTPS 配置
在 Spring Boot 中启用 HTTPS:
生成 SSL 证书:
keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650配置 application.properties:
server.port=8443 server.ssl.key-store=classpath:keystore.p12 server.ssl.key-store-password=changeit server.ssl.key-store-type=PKCS12 server.ssl.key-alias=tomcat
6.3 常见安全防护
1. XSS 防护:
- 对用户输入进行过滤和转义
- 设置 Content Security Policy (CSP) 响应头
- 使用框架的自动转义功能
2. CSRF 防护:
- 使用 Spring Security 的 CSRF 防护
- 为状态更改请求(POST/PUT/DELETE)添加 CSRF token
- 使用 SameSite Cookie 属性
// Spring Security 配置 CSRF
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
// 其他配置...3. SQL 注入防护:
- 使用参数化查询(PreparedStatement)
- 使用 ORM 框架(MyBatis, Hibernate)
- 避免拼接 SQL 语句
七、实用技巧与最佳实践
7.1 日志管理
使用 SLF4J + Logback 进行日志管理:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserService {
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
public User getUserById(Long id) {
logger.info("正在查询用户,ID: {}", id);
try {
User user = userRepository.findById(id);
if (user == null) {
logger.warn("用户不存在,ID: {}", id);
}
return user;
} catch (Exception e) {
logger.error("查询用户时发生错误,ID: {}", id, e);
throw e;
}
}
}7.2 全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFound(ResourceNotFoundException ex) {
ErrorResponse error = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
"资源不存在",
ex.getMessage()
);
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGlobalException(Exception ex) {
ErrorResponse error = new ErrorResponse(
HttpStatus.INTERNAL_SERVER_ERROR.value(),
"服务器内部错误",
ex.getMessage()
);
return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
// 自定义错误响应类
@Data
@AllArgsConstructor
public static class ErrorResponse {
private int status;
private String title;
private String message;
}
}7.3 配置管理
使用 Spring Boot 的配置管理:
# application.properties
app.name=My Application
app.version=1.0.0
# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 连接池配置
spring.datasource.hikari.maximum-pool-size=10使用 @Value 注入配置:
@RestController
public class ConfigController {
@Value("${app.name}")
private String appName;
@Value("${app.version}")
private String appVersion;
@GetMapping("/config")
public Map<String, String> getConfig() {
Map<String, String> config = new HashMap<>();
config.put("name", appName);
config.put("version", appVersion);
return config;
}
}或者使用类型安全的配置类:
@Configuration
@ConfigurationProperties(prefix = "app")
@Data
public class AppConfig {
private String name;
private String version;
private String description;
}