【黑马JavaWeb+AI知识梳理】Web后端开发08 - 总结

JavaWeb后端架构系统学习笔记

一、整体架构流程

1.1 请求-响应路径
复制代码
流程说明:
请求从浏览器发出,依次经过 过滤器 → 拦截器 → Controller → Service → Dao → 数据库
响应路径为反向流程:数据库 → Dao → Service → Controller → 拦截器 → 过滤器 → 浏览器
1.2 分层架构解析

分层架构 是JavaWeb后端开发的核心设计模式,它将复杂的系统划分为多个独立层级,每个层级专注于特定功能,显著降低了系统耦合度,提高了可维护性和扩展性

层级 职责 技术栈 与相邻层级关系
过滤器层 预处理/后处理所有请求 Servlet API、Filter 接收浏览器请求,传递给拦截器层
拦截器层 拦截特定请求,执行横切关注点 Spring Interceptor 接收过滤器处理后的请求,传递给Controller层
Controller层 接收前端请求,调用业务逻辑 Spring MVC、@RestController 接收拦截器处理后的请求,调用Service层
Service层 处理核心业务逻辑 Spring Service、@Transactional 接收Controller请求,协调多个Dao操作
Dao层 数据持久化操作 MyBatis、JPA、JDBC 执行Service层的数据访问指令
数据库层 存储和管理数据 MySQL、PostgreSQL 接收并执行Dao层的SQL语句
1.3 架构优势

分层架构提供了以下关键优势:

  1. 职责清晰:每个层级只关注特定功能,避免代码混杂 。
  2. 解耦性强:层级间通过接口通信,降低模块依赖 。
  3. 扩展性高:新增功能只需修改对应层级,不影响其他模块 。
  4. 复用性好:通用组件(如工具类、实体类)可跨层级复用 。
  5. 维护简便:问题定位和修复集中在特定层级,效率显著提高。

二、核心组件解析

2.1 过滤器(Filter)
2.1.1 概念与作用

过滤器 是基于Servlet规范的组件,对所有HTTP请求进行预处理和响应的后处理 。它不依赖具体业务逻辑,是Web应用的第一道防线

2.1.2 常见用途
  • 编码设置:统一处理请求编码(如UTF-8)
  • 日志记录:记录请求路径、参数和响应时间
  • 安全防护:防止XSS攻击、CSRF攻击等
  • 请求头处理:添加或修改HTTP头信息
  • 权限校验:基础权限验证(如未登录用户重定向)
2.1.3 实现方式

通过实现Filter接口并配置web.xml或使用注解注册过滤器:

java 复制代码
public class EncodingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
        req.setCharacterEncoding("UTF-8");
        res.setCharacterEncoding("UTF-8");
        chain.doFilter(req, res);
    }
    // 初始化和销毁方法略
}

在web.xml中配置

xml 复制代码
<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>com.example过滤器 EncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
2.2 拦截器(Interceptor)
2.2.1 概念与作用

拦截器 是Spring框架提供的组件,拦截特定请求,执行横切关注点 。与过滤器不同,拦截器仅作用于Spring管理的请求更灵活且业务关联性更强

2.2.2 与过滤器的区别
特性 过滤器 拦截器
规范 Servlet规范 Spring框架层
作用范围 所有请求 Spring管理的请求
配置方式 web.xml或注解 Spring配置类或注解
执行时机 在Servlet容器层面 在Spring MVC层面
扩展性 较低 较高
2.2.3 常见用途
  • 登录状态检查:结合Cookie/Session或JWT验证用户身份
  • 权限控制:基于角色(RBAC)或属性(ABAC)验证访问权限
  • 性能监控:记录方法执行时间,分析系统瓶颈
  • 请求参数校验:验证请求参数格式和有效性
  • 日志记录:记录业务方法执行日志
2.2.4 实现方式

通过实现HandlerInterceptor接口并注册到Spring容器

java 复制代码
@Component
public class AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 权限校验逻辑
        return true; // 放行请求
    }
}

在Spring配置类中注册拦截器

java 复制代码
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private AuthInterceptor authInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor)
                .addPathPatterns("/api/**") // 拦截所有API请求
                .excludePathPatterns("/login", "/register"); // 排除登录注册接口
    }
}
2.3 Controller层
2.3.1 职责与特点

Controller层 是用户请求的入口,负责接收前端请求、调用业务逻辑并返回响应结果 。它不处理业务逻辑仅作为请求的中转站

2.3.2 技术栈与注解

主要技术栈:Spring MVC、Spring Boot、RESTful API设计

常用注解

java 复制代码
@RestController  // 表示这是一个RESTful控制器,返回数据直接序列化为JSON
@RequestMapping("/api/user")  // 定义基础请求路径
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/{id}")  // 处理GET请求
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        User user = userService.findById(id);
        return ResponseEntity.ok(user);
    }

    @PostMapping  // 处理POST请求
    public ResponseEntity<User> createUser(@Valid @RequestBody UserCreateRequest request) {
        User user = userService.createUser(request);
        return ResponseEntity.created(URI.create("/api/user/" + user.getId())).body(user);
    }
}
2.3.3 参数接收方式

Spring MVC提供了多种参数接收方式,根据需求灵活选择:

  • @RequestParam:接收查询参数或请求体中的简单参数
  • @RequestBody:接收请求体中的复杂对象(如JSON数据)
  • @PathVariable:接收URL中的动态路径参数
  • @CookieValue:接收请求中的Cookie值
  • @SessionAttribute:接收Session中的属性值
2.4 Service层
2.4.1 职责与特点

Service层 是业务逻辑的核心,封装系统的核心业务规则和流程 。它通常不直接与数据库交互而是通过调用Dao层实现数据访问 。Service层是事务管理的主要场所保证业务操作的原子性

2.4.2 技术栈与注解

主要技术栈:Spring Service、事务管理、AOP

常用注解

java 复制代码
@Service  // 表示这是一个业务服务类
public class UserService {
    @Autowired
    private UserMapper userMapper;

    @Transactional  // 声明事务管理
    public void updateUser(User user) {
        userMapper.update(user);
        // 其他业务操作...
    }
}
2.5 Dao层(Data Access Object)
2.5.1 职责与特点

Dao层 负责与数据库交互执行数据的增删改查操作 。它不包含业务逻辑仅专注于数据访问 。在Spring框架中,通常通过JDBC、MyBatis或JPA实现

2.5.2 实现方式

MyBatis实现

java 复制代码
@Mapper  // 声明这是一个MyBatis映射接口
public interface UserMapper {
    @Select("SELECT * FROM user WHERE id = #{id}")
    User getUserById(Long id);

    @Update("UPDATE user SET name = #{name}, age = #{age} WHERE id = #{id}")
    void updateUser(User user);
}

JPA实现

java 复制代码
@Repository  // 声明这是一个数据访问层组件
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByName(String name);
    List<User> findByAgeLessThanEqual(Integer maxAge);
}

三、核心技术栈支持

3.1 IOC(Inversion of Control)控制反转
3.1.1 概念

IOC是Spring框架的核心思想将对象的创建和管理权从程序员转移到Spring容器对象的依赖关系通过容器自动装配而非手动创建

3.1.2 实现机制

Spring容器通过反射机制工厂模式实现IOC :

  1. 读取配置:从XML或注解中获取Bean定义
  2. 实例化对象:根据类信息动态创建实例
  3. 依赖注入:根据依赖关系自动注入其他Bean
  4. 管理生命周期:控制Bean的初始化和销毁时机
3.1.3 容器类型

Spring提供了两种主要IOC容器:

容器类型 特点 适用场景
BeanFactory 基础容器,延迟加载,轻量级 资源受限环境,如移动端
ApplicationContext 扩展型容器,支持预初始化单例、事件机制等 企业级应用,如Web应用
3.2 DI(Dependency Injection)依赖注入
3.2.1 概念

DI是IOC的具体实现方式通过容器自动将对象依赖注入到目标对象中它解决了传统开发中手动管理依赖的繁琐问题使代码更简洁、可维护性更高

3.2.2 注入方式

Spring支持两种主要依赖注入方式:

构造器注入 :通过构造方法传递依赖,强制依赖不可变适合强制依赖场景

java 复制代码
@Service
public class UserService {
    private final IDEAcess Dal;

    @Autowired
    public UserService(IDataAccess Dal) {
        this.Dal = Dal;
    }
}

设值注入 :通过setter方法或字段注解注入依赖,灵活性更高适合可选依赖场景

java 复制代码
@Service
public class UserService {
    @Autowired
    private IDEAcess Dal;
}
3.2.3 依赖管理

通过**@Autowired@Resource**注解实现自动装配 :

java 复制代码
@Autowired
private IDEAcess Dal;  // 自动注入IDEAcess类型的Bean
3.3 AOP(Aspect Oriented Programming)面向切面编程
3.3.1 概念

AOP是Spring框架的另一个核心特性通过横切面(Aspect)将通用功能(如日志、事务)与业务逻辑分离它解决了传统开发中重复代码的问题使代码更简洁、可维护性更高

3.3.2 通知类型

Spring AOP支持五种主要通知类型:

通知类型 注解 执行时机 典型应用场景
前置通知 @Before 目标方法执行前 方法调用前记录日志
后置通知 @After 目标方法执行后 方法调用后释放资源
返回后通知 @AfterReturning 方法正常返回后 方法成功执行后的记录
异常通知 @AfterThrowing 方法抛出异常后 方法异常时的错误处理
环绕通知 @Around 完全围绕目标方法 事务管理、方法执行计时
3.3.3 切点表达式

切点表达式 用于定义哪些方法会被AOP拦截

java 复制代码
@Aspect
@Component
public class LoggingAspect {
    // 定义切点:拦截所有Service层的方法
    @Pointcut("execution(* com.example.service.*.*(..))")
    private void serviceMethods() {}

    // 定义切点:拦截所有带有@Log注解的方法
    @Pointcut("@annotation(com.example.annotation.Log)")
    private void logAnnotatedMethods() {}

    // 使用切点
    @Before("serviceMethods() || logAnnotatedMethods()")  // 拦截Service层方法或带有@Log注解的方法
    public void logBefore(JoinPoint joinPoint) {
        String method = joinPoint.getSignature().getName();
        String args = Arrays.toString(joinPoint.getArgs());
        System.out.println("方法调用前: " + method + " 参数: " + args);
    }
}
3.3.4 实际应用场景

AOP在JavaWeb中的典型应用

  1. 日志记录:记录方法执行前后的信息
  2. 事务管理:通过@Around通知实现事务控制
  3. 权限控制:在方法执行前验证用户权限
  4. 性能监控:记录方法执行时间,分析系统瓶颈
  5. 异常处理:统一处理方法抛出的异常
3.4 事务管理
3.4.1 概念

事务管理 确保一系列数据库操作要么全部成功,要么全部失败保证数据的一致性和完整性 。在JavaWeb中,通常通过Spring的声明式事务管理实现

3.4.2 传播行为

事务传播行为 定义方法调用时如何处理事务

传播行为 注解值 行为说明 适用场景
Required 传播行为值 支持当前事务,无则新建 大多数业务方法
RequiresNew 传播行为值 挂起当前事务,新建独立事务 需要独立事务的方法
Never 传播行为值 禁止事务,若存在则抛异常 必须非事务的方法
Mandatory 传播行为值 必须在事务中执行 必须事务的方法
Support 传播行为值 支持事务但不强制 可选事务的方法
3.4.3 隔离级别

事务隔离级别 定义事务之间如何隔离平衡并发性能与数据一致性

隔离级别 注解值 特点 适用场景
默认 默认值 使用数据库默认级别(通常为READ_COMMITTED) 大多数场景
读未提交 隔离级别值 允许脏读,但并发性能高 对一致性要求不高的场景
读已提交 隔离级别值 禁止脏读,允许不可重复读 一般业务场景
可重复读 隔离级别值 禁止脏读和不可重复读,但允许幻读 需要高一致性的场景
序列化 隔离级别值 串行化事务,完全隔离但性能差 对一致性要求极高的场景
3.4.4 事务管理实现

通过@Transactional注解实现声明式事务管理

java 复制代码
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    @Transactional propagation =传播行为, isolation =隔离级别)
    public void updateUser(User user) {
        userMapper.update(user);
        // 其他业务操作...
    }
}
3.5 全局异常处理
3.5.1 概念

全局异常处理异常捕获和处理逻辑集中管理避免在每个方法中重复编写异常处理代码它提高了代码的复用性和可维护性

3.5.2 实现方式

通过@ControllerAdvice注解实现

java 复制代码
@ControllerAdvice
@RestController
public class GlobalExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    // 捕获参数缺失异常
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public Result handleMissingParam(MissingServletRequestParameterException ex) {
        logger.error("缺少必要参数: {}", ex.getMessage());
        return Result.error(400, "缺少必要参数", ex.getMessage());
    }

    // 捕获空指针异常
    @ExceptionHandler(NullPointerException.class)
    public Result handleNullPointerException(NullPointerException ex) {
        logger.error("空指针异常: {}", ex.getMessage());
        return Result.error(500, "系统内部错误", "空指针异常");
    }

    // 捕获自定义业务异常
    @ExceptionHandler(BusinessException.class)
    public Result handleBusinessException(BusinessException ex) {
        logger.error("业务异常: {}", ex.getMessage());
        return Result.error(ex码, ex信息, ex详情);
    }
}
3.5.3 异常封装

建议将异常封装为统一格式

json 复制代码
{
    "code": 状态码(数字),
    "msg": 中文解析(字符串),
    "data": 返回数据(对象),
    "traceId": 请求追踪ID(字符串)
}

四、辅助功能模块

4.1.1 概念

Cookie存储在客户端的小型文本数据通常用于标识用户身份Session服务器端存储的用户状态信息与Cookie配合使用实现用户身份保持

4.1.2 配置与使用

Cookie操作

java 复制代码
// 设置Cookie
@GetMapping("/set-cookie")
public String setCookie(HttpServletResponse response) {
    Cookie cookie = new Cookie("user_token", "abc123");
    cookie.setMaxAge(3600);  // 有效期1小时
    cookie.setPath("/");  // 全站有效
    cookie.setHttpOnly(true);  // 防止XSS攻击
    response.addCookie cookie);
    return "Cookie设置成功";
}

// 读取Cookie
@GetMapping("/read-cookie")
public String readCookie(@CookieValue(name = "user_token", defaultValue = "") String token) {
    if (token.isEmpty()) {
        return "未找到用户Token";
    }
    return "当前用户Token: " + token;
}

// 删除Cookie
@GetMapping("/delete-cookie")
public String deleteCookie(HttpServletResponse response) {
    Cookie cookie = new Cookie("user_token", null);
    cookie.setMaxAge(0);  // 立即过期
    response.addCookie cookie);
    return "Cookie已删除";
}

Session配置

在application.properties中设置Session超时时间:

properties 复制代码
server.servlet.session.timeout=30m  # Session有效期30分钟

Session操作

java 复制代码
// 设置Session属性
@GetMapping("/set-session")
public String setSession(HttpServletRequest request) {
    HttpSession session = request.getSession();
    session.setAttribute("cart", Arrays.asList("item1", "item2"));
    return "Session数据已存储";
}

// 读取Session属性
@GetMapping("/get-session")
public String getSession(HttpServletRequest request) {
   (HttpSession session = request sessions);
    List<String> cart = (List<String>) session.getAttribute("cart");
    return "购物车内容: " + (cart != null ? cart : "空");
}
4.1.3 分布式Session管理

在微服务架构中,推荐使用Redis实现分布式Session共享

依赖引入

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

配置文件

properties 复制代码
spring redis host=localhost
spring redis port=6379
spring session store-type=redis

启用Redis Session

java 复制代码
@EnableRedisHttpSession
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
4.2 JWT(JSON Web Token)
4.2.1 概念

JWT是一种基于令牌的无状态认证方案将用户信息加密后存储在令牌中服务端无需存储Session它特别适合分布式系统和移动端应用

4.2.2 JWT结构

一个标准的JWT由三个部分组成:

  1. Header(头部):声明令牌类型和加密算法
  2. Payload(负载):存储用户信息和声明(如过期时间)
  3. Signature(签名):验证令牌完整性和来源

三部分之间用英文句点分隔,格式为:

复制代码
Header base64Url编码 . Payload base64Url编码 . Signature
4.2.3 JWT工具类实现

使用JJWT库生成和解析JWT

java 复制代码
@Component
public class JWTUtil {
    // 从配置文件获取密钥
    @Value("${jwt秘密}")
    private String secret;

    // 生成JWT
    public String generateToken(Map<String, Object> claims) {
        return JWT.create()
                .withClaim("个人信息", claims)
                .withExpiresAt(new Date(System.currentTimeMillis() + 3600000))  // 1小时后过期
                .sign(Algorithm.HMAC256(secret));
    }

    // 解析JWT
    public DecodedJWT decodeToken(String token) {
        try {
            return JWT.decode(token);
        } catch (JWTVerificationException ex) {
            throw new JWTDecodeException("无效的Token", ex);
        }
    }

    // 验证JWT有效性
    public boolean validateToken(String token) {
        try {
            DecodedJWT decodedJWT = decodeToken(token);
            return !decodedJWT.is糖过期();
        } catch (JWTDecodeException ex) {
            return false;
        }
    }

    // 获取JWT中的用户信息
    public Map<String, Object> getUserInfo(String token) {
        DecodedJWT decodedJWT = decodeToken(token);
        return decodedJWT.getClaim("个人信息").asMap();
    }
}
4.2.4 JWT拦截器实现

自定义拦截器验证JWT令牌

java 复制代码
@Component
public class JWTInterceptor implements HandlerInterceptor {
    @Autowired
    private JWTUtil jwtUtil;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 从请求头获取Token
        String token = request.getHeader("Authorization");
        if (token == null) {
            // 从请求参数获取Token
            token = request.getParameter("token");
        }

        // 验证Token
        if (token == null || !jwtUtil.validateToken(token)) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            response.setContentType("application/json");
            try {
                response.getWriter().write JSON格式的错误响应);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return false; // 拒绝访问
        }

        // 将用户信息存入请求属性
        Map<String, Object> userInfo = jwtUtil.getUserInfo(token);
        request.setAttribute("个人信息", userInfo);

        return true; // 放行请求
    }
}
4.2.5 安全最佳实践

JWT安全配置建议

  1. 密钥管理:使用环境变量存储JWT密钥,避免硬编码
  2. IP绑定:在Payload中设置客户端IP,验证时检查IP一致性
  3. 加密算法:使用AES等强加密算法保护Token
  4. 设置合理过期时间:根据业务场景设置Token有效期
  5. 定期更新密钥:定期更换JWT签名密钥,降低密钥泄露风险
4.3 阿里云OSS
4.3.1 概念

阿里云OSS是对象存储服务用于存储和管理非结构化数据(如图片、视频)它提供了高可用、高可靠的存储解决方案适合Web应用的静态资源存储

4.3.2 配置与使用

依赖引入

xml 复制代码
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.19.0</version>
</dependency>

配置文件

properties 复制代码
# 阿里云OSS配置
oss endpoint=oss-cn-hangzhou.aliyuncs.com
oss bucket name=my-bucket
oss access key id=YOUR_ACCESS_KEY_ID
oss access key secret=YOUR_ACCESS_KEY_SECRET

文件上传示例

java 复制代码
@RestController
@RequestMapping("/api/oss")
public class OSSController {
    @Value("${oss endpoint}")
    private String endpoint;
    @Value("${oss bucket name}")
    private String bucketName;
    @Value("${oss access key id}")
    private String accessKeyId;
    @Value("${oss access key secret}")
    private String accessKeySecret;

    @PostMapping("/upload")
    public Result uploadFile(@RequestParam("file") MultipartFile file) {
        try {
            // 创建OSS客户端
            OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);

            // 上传文件
            String key = "images/" + UUID.randomUUID().toString() + "." + file.getExtension();
            ossClient.putObject(bucketName, key, file.getInputStream());

            // 关闭客户端
            ossClient.close();

            // 返回文件URL
            String url = "https://"+ bucketName + "." + endpoint + "/" + key;
            return Result.success(url);
        } catch (IOException e) {
            e.printStackTrace();
            return Result.error("文件上传失败");
        }
    }
}

文件下载示例

java 复制代码
@GetMapping("/download/{key}")
public void downloadFile(HttpServletRequest request, HttpServletResponse response, @PathVariable String key) {
    try {
        // 创建OSS客户端
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);

        // 获取文件信息
        ObjectListing listing = ossClient.listObjects (bucketName, key);
        OSSObject ossObject = ossClient.getObject (bucketName, key);

        // 设置响应头
        response.reset();
        response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(key, "UTF-8"));
        response.addHeader("Content-Type", ossObject.getMetadata().getContentType());
        response.addHeader("Content-Length", String.valueOf(ossObject.getMetadata(). ContentLength));

        // 将文件流写入响应
       IOUtils.copy(ossObject.getObjectContent(), response.getOutputStream());

        // 关闭客户端
        ossClient.close();
    } catch (Exception e) {
        e.printStackTrace();
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
    }
}
4.3.3 安全配置建议

OSS安全配置建议

  1. 最小权限原则:为RAM用户分配最小必要权限
  2. 开启防盗链:防止他人直接访问OSS资源
  3. 设置合理的过期时间:为临时访问链接设置过期时间
  4. 使用HTTPS:确保数据传输安全
  5. 定期轮换密钥:降低密钥泄露风险
4.4 MyBatis
4.4.1 概念

MyBatis是持久层框架通过XML或注解配置SQL语句简化了JDBC操作它提供了灵活的数据库操作能力适合复杂SQL场景

4.4.2 整合Spring Boot

依赖引入

xml 复制代码
<dependency>
    <groupId>org mybatis spring. boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>

配置文件

properties 复制代码
# MyBatis配置
mybatis mapper locations=classpath:mapper/*.xml
mybatis typealiases package=com.example entity
mybatis configuration map underying column with骆驼命名法=true

动态SQL示例

xml 复制代码
<select id="getUserByCondition" resultType="User">
    SELECT * FROM user
    <where>
        <if test="name != null and name != ''">
            AND name LIKE CONCAT('%', #{name}, '%')
        </if>
        <if test="age != null">
            AND age = #{age}
        </if>
        <if test="status != null">
            AND status = #{status}
        </if>
    </where>
    ORDER BY id DESC
</select>

注解方式

java 复制代码
@Mapper
public interface UserMapper {
    @Select("SELECT * FROM user WHERE id = #{id}")
    User getUserById(Long id);

    @Insert("INSERT INTO user (name, age) VALUES (#{name}, #{age})")
    @Options(keyProperty = "id", useActualParamName = true)
    void insertUser(User user);

    @Update("UPDATE user SET name = #{name}, age = #{age} WHERE id = #{id}")
    void updateUser(User user);

    @Delete("DELETE FROM user WHERE id = #{id}")
    void.deleteUser(Long id);
}
4.4.4 安全配置建议

MyBatis安全配置建议

  1. 使用参数化查询 :避免SQL注入,使用#{param}而非${param}
  2. 开启SQL日志:调试阶段开启,生产环境关闭
  3. 设置合理的超时时间:防止长时间等待导致资源浪费
  4. 使用连接池:如HikariCP,提高数据库连接效率
  5. 定期检查SQL性能:使用Explain分析慢查询

五、架构总结与最佳实践

5.1 架构总结

JavaWeb后端架构具有以下核心特点:

  1. 分层清晰:从浏览器到数据库的明确请求-响应路径
  2. 职责分明:各层专注自身任务,降低耦合
  3. 扩展性强:易于引入新功能(如Redis缓存、消息队列)
  4. 安全可控:通过拦截器和JWT实现权限控制
  5. 性能可调:通过缓存、索引优化提升系统性能
  6. 可维护性高:分层设计使问题定位和修复更高效
5.2 最佳实践建议
5.2.1 模块化设计

按功能+层次组合拆分模块

text 复制代码
项目名/
├── parent/               # 父工程,管理依赖和配置
├── common/                # 公共模块
│   ├── config/            # 配置文件
│   ├── utils/             # 工具类
│   └── entity/            # 实体类
├── order/                  # 订单模块
│   ├── controller/
│   ├── service/
│   └── mapper/
├── user/                   # 用户模块
│   ├── controller/
│   ├── service/
│   └── mapper/
└── web/                    # Web入口模块
5.2.2 安全实践

安全是JavaWeb架构的核心考量

  1. 输入验证:对所有用户输入进行验证,防止注入攻击
  2. 权限控制:实现细粒度权限管理,如RBAC或ABAC模型
  3. 加密传输:使用HTTPS确保数据传输安全
  4. 定期安全审计:检查系统漏洞和配置问题
  5. 使用安全框架:如Spring Security、Shiro等
5.2.3 性能优化

性能优化是JavaWeb架构的关键

  1. 缓存策略:使用Redis缓存高频访问数据

    java 复制代码
    @Cacheable(value = "users", key = "#id")
    public User getUserById(Long id) {
        return userMapper.getUserById(id);
    }
  2. 数据库优化:合理设计索引,避免全表扫描

    sql 复制代码
    CREATE INDEX idx_user_name ON user(name);
  3. 异步处理:使用消息队列处理耗时操作

    java 复制代码
    @Async
    public void sendEmail(User user, String content) {
        // 发送邮件逻辑
    }
  4. 连接池管理:配置合理的数据库连接池参数

    properties 复制代码
    spring.datasource.hikari.maximum-pool-size=20
    spring.datasource.hikari.minimum-idle=5
  5. 监控与日志:使用ELK栈或Spring Boot Actuator监控系统状态

5.2.4 部署实践

现代部署实践提升系统可用性

  1. 容器化部署:使用Docker容器化应用

    dockerfile 复制代码
    FROM openjdk:17-jre-slim
    VOLUME /tmp
    COPY target/*.jar app.jar
    ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
  2. 微服务架构:使用Spring Cloud实现微服务

    java 复制代码
    @SpringBootApplication
    @EnableEurekaClient  // 服务注册
    public class User服务中心 {
        public static void main(String[] args) {
            SpringApplication.run(User服务中心.class, args);
        }
    }
  3. 配置中心:使用Spring Cloud Config实现动态配置

    properties 复制代码
    # 配置中心地址
    spring.config尿服务器=http://config-server:8888
  4. 服务网关:使用Spring Cloud Gateway实现统一入口

    yaml 复制代码
    spring:
      cloud:
        gateway:
          routes:
          - id: user-service
            uri: lb://USER-SERVICE
            predicates:
            - Path=/api/user/**
  5. 断路器模式:使用Hystrix或Resilience4j实现容错

    java 复制代码
    @HystrixCommand(fallbackMethod = "fallback")
    public User getUserById(Long id) {
        return userMapper.getUserById(id);
    }
    
    public User fallback(Long id) {
        // 回退逻辑
        return new User(id, "匿名用户", 0);
    }
5.2.5 监控与维护

完善的监控体系是架构成功的关键

  1. 健康检查:使用Spring Boot Actuator提供健康检查端点

    properties 复制代码
    management端点 enabled end points=health,info,env
    management端点暴露端点=web
  2. 日志管理:使用ELK栈集中管理日志

    java 复制代码
    @Value("${log.level}")
    private String logLevel;
    
    @Bean
    public滚筒文件日志配置配置() {
        Logback滚筒文件日志配置配置 = new滚筒文件日志配置();
        configuration.setFile(logPath + "/app.log");
        configuration.set contexts contexts);
        configuration.set contexts contexts);
        return configuration;
    }
  3. 性能监控:使用Prometheus+Grafana监控系统性能

    java 复制代码
    @Bean
    public米特里克斯() {
        return new米特里克斯();
    }
    
    @Bean
    public斯普林米特里克斯配置() {
        SpringMetricsConfig config = new SpringMetricsConfig();
        config.set contexts contexts);
        return config;
    }
  4. 自动化测试:使用JUnit5、Mockito进行单元测试和集成测试

    java 复制代码
    @SpringBootTest
    @AutoConfiguration类
    class UserServiceTest {
        @Autowired
        private UserService userService;
    
        @MockBean
        private UserMapper userMapper;
    
        @Test
        void测试获取用户信息() {
            // 模拟数据库返回
            User user = new User(1L, "测试用户", 25);
            when(userMapper.getUserById(1L)).thenReturn(user);
    
            // 调用服务方法
            User result = userService.getUserById(1L);
    
            // 验证结果
            assertEquals("测试用户", result.getName());
        }
    }
  5. 持续集成:使用Jenkins或GitHub Actions实现自动化构建和测试

    yaml 复制代码
    name: Java CI with Maven
    
    on:
      push:
        branches: [main]
      pull_request:
        branches: [main]
    
    jobs:
      build:
        runs-on: ubuntu-latest
    
        steps:
        - uses: actions/checkout@v2
        - name: Set up JDK 17
          uses: actions/setup-java@v2
          with:
            java-version: '17'
            distribution: 'temurin'
        - name: Build with Maven
          run: mvn clean package -DskipTests
        - name: Run tests
          run: mvn test
5.3 架构演进路径

JavaWeb架构可随系统规模发展而演进

  1. 单体架构:小型项目,所有功能集中在单一应用
  2. 模块化单体架构:中型项目,按功能或层次拆分模块
  3. 微服务架构:大型分布式系统,按业务拆分服务
  4. 云原生架构:超大规模系统,使用容器化和Serverless技术

六、补充知识

6.1 分层架构设计原则

分层架构应遵循以下核心原则

  1. 高内聚:每个层级内部功能紧密相关,减少内部冗余
  2. 低耦合:层级间依赖最小化,通过接口通信
  3. 单一职责:每个层级只关注单一功能,避免职责混杂
  4. 可替换性:层级可独立替换,如替换数据库或认证方式
  5. 清晰边界:层级间有明确的接口定义和数据格式
6.2 模块间依赖管理

模块间依赖应遵循以下规则

  1. 单向依赖:层级间依赖方向一致,避免循环依赖
  2. 接口隔离:上层通过接口调用下层,而非直接依赖实现类
  3. 依赖版本统一:使用父工程的dependencyManagement统一管理依赖版本
  4. 避免过度拆分:模块粒度适中,避免因拆分过多增加维护成本
  5. 考虑未来扩展:预留接口和扩展点,便于后续功能扩展
6.3 代码规范与风格

良好的代码规范是架构成功的基础

  1. 命名规范 :清晰表达含义,如User服务中心UserMapper
  2. 注释规范:关键逻辑添加注释,但避免过度注释
  3. 异常处理:统一异常处理策略,避免重复代码
  4. 日志规范:使用统一的日志框架和格式
  5. 代码复用:提取公共代码为工具类或父类,提高复用性

七、常见问题与解决方案

7.1 依赖冲突问题

现象:编译或运行时出现类冲突

解决方案

  1. 使用mvn dependency:tree分析依赖树
  2. 通过<exclusion>排除冲突依赖
  3. 在父工程<dependencyManagement>中统一版本
7.2 构建顺序问题

现象:模块间依赖关系导致构建失败

解决方案

  • 在聚合工程<modules>标签中声明模块顺序
  • 确保子模块pom.xml正确声明依赖关系
  • 使用<dependency>标签明确指定依赖范围
7.3 事务管理问题

现象:事务未按预期提交或回滚

解决方案

  1. 确保Service层方法使用@Transactional注解
  2. 检查事务传播行为和隔离级别设置
  3. 避免在Service层内部调用其他Service方法,使用AOP或代理模式
7.4 JWT安全问题

现象:Token被截获或篡改

解决方案

  1. 使用强加密算法(如AES)保护Token
  2. 实现Token IP绑定,验证请求IP与Payload中的IP是否一致
  3. 设置合理的Token过期时间,避免长期有效
  4. 定期轮换签名密钥,降低密钥泄露风险
  5. 实现Token黑名单机制,支持主动失效
7.5 数据库性能问题

现象:查询速度慢,系统响应延迟高

解决方案

  1. 使用Explain分析慢查询
  2. 合理设计索引,避免全表扫描
  3. 使用缓存(如Redis)减少数据库访问次数
  4. 分库分表处理大数据量场景
  5. 使用连接池管理数据库连接

八、面试高频考点

8.1 分层架构设计

高频问题

  • 请描述JavaWeb的分层架构及其各层职责
  • 过滤器和拦截器的区别是什么?
  • Controller层为什么不应该包含业务逻辑?

回答要点

  • 分层架构包括:浏览器层、过滤器层、拦截器层、Controller层、Service层、Dao层、数据库层
  • 过滤器基于Servlet规范,作用于所有请求;拦截器基于Spring框架,仅拦截Spring管理的请求
  • Controller层负责接收请求和返回响应,业务逻辑应放在Service层,保持职责清晰
8.2 IOC/DI原理

高频问题

  • 什么是IOC?其核心思想是什么?
  • DI和IOC的关系是什么?
  • Spring的依赖注入有哪些方式?

回答要点

  • IOC(控制反转)将对象创建和管理权从程序员转移到容器
  • DI(依赖注入)是IOC的具体实现方式,通过容器自动注入依赖
  • Spring支持设值注入(setter注入)和构造器注入两种主要方式
8.3 AOP应用

高频问题

  • 什么是AOP?与OOP的区别是什么?
  • Spring AOP支持哪些通知类型?
  • 如何实现一个日志记录的AOP切面?

回答要点

  • AOP通过横切面将通用功能与业务逻辑分离,解决OOP中重复代码问题
  • Spring AOP支持前置通知、后置通知、返回后通知、异常通知和环绕通知
  • 使用@Aspect注解定义切面,@Before、@After等注解定义通知,@Pointcut定义切点
8.4 事务管理

高频问题

  • Spring事务传播行为有哪些?
  • 事务隔离级别如何选择?
  • 如何保证分布式系统中的事务一致性?

回答要点

  • 常见传播行为包括REQUIRED、REQUIRES_NEW、NEVER等
  • 隔离级别根据业务需求选择,默认为READ_COMMITTED
  • 分布式事务可使用TCC、Saga或Seata等方案实现
8.5 JWT认证

高频问题

  • JWT认证原理是什么?
  • JWT与Session认证的区别是什么?
  • 如何保证JWT的安全性?

回答要点

  • JWT将用户信息加密后存储在令牌中,服务端无需存储Session
  • JWT适合分布式系统和移动端,Session适合传统Web应用
  • JWT安全性通过密钥管理、IP绑定、加密算法和合理过期时间保证
8.6 分布式架构

高频问题

  • 微服务架构有哪些优势?
  • 如何实现微服务间的通信?
  • 如何解决微服务中的配置管理问题?

回答要点

  • 微服务架构优势包括服务自治、高扩展性、技术栈灵活等
  • 微服务通信可通过REST API、RPC(如Dubbo)或消息队列(如RabbitMQ)实现
  • 使用Spring Cloud Config或Nacos实现微服务配置中心

九、总结

JavaWeb后端架构是构建企业级应用的基础掌握其核心组件和技术栈对开发高质量应用至关重要分层架构通过职责分离和接口定义,提供了良好的可维护性和扩展性IOC/DI和AOP等Spring核心功能,使开发更加简洁高效随着系统规模扩大,架构可从单体逐步演进到微服务和云原生架构适应不同业务需求

在实际开发中,应根据项目规模和团队能力选择合适的架构复杂度小型项目可采用模块化单体架构中大型项目推荐使用微服务架构无论选择哪种架构,都应遵循分层设计原则,确保系统清晰、安全、高效

相关推荐
heartbeat..2 小时前
Java IO 流完整解析:原理、分类、使用规范与最佳实践
java·开发语言·io·文件
冬奇Lab2 小时前
【Cursor进阶实战·01】Figma设计稿一键还原:Cursor + MCP让前端开发提速10倍
android·前端·后端·个人开发·figma
Justin_192 小时前
k8s常见问题(3)
java·开发语言
Knight_AL2 小时前
Java 内存溢出(OOM)排查实战指南:从复现到 MAT Dump 分析
java·开发语言
糯诺诺米团2 小时前
C++多线程打包成so给JAVA后端(Ubuntu)<1>
java·开发语言
刘宇涵492 小时前
递归Java
java
superman超哥2 小时前
Rust 泛型参数的使用:零成本抽象的类型级编程
开发语言·后端·rust·零成本抽象·rust泛型参数·类型级编程
代码不停2 小时前
Spring Boot快速入手
java·spring boot·后端
-Excalibur-2 小时前
关于计算机网络当中的各种计时器
java·c语言·网络·c++·笔记·python·计算机网络