未经许可,不得转载。
文章目录

客户端服务端交互流程
在Java Web应用中,URL请求流程是客户端与服务器之间交互的核心过程。它描述了从用户发起请求到服务器返回响应的完整生命周期。
客户端服务端交互的全流程如下。
1、用户发起请求。
2、浏览器将域名解析为服务器的IP地址。
3、浏览器通过TCP协议与服务器建立连接。
4、浏览器将请求信息(如URL、请求头、请求体等)打包成HTTP请求报文,发送到服务器。
5、服务器接收到HTTP请求后,将其解析为Java对象(如HttpServletRequest)。
接着,请求到达MVC(Model-View-Controller)架构。

在后端,请求的处理流程如下:
1、请求首先经过过滤器(Filter)和拦截器(Interceptor),用于执行一些全局操作,如权限验证、日志记录、字符编码设置等。
2、根据请求的URL映射到对应的控制器方法。
3、控制器方法接收请求参数,调用服务层(Service)处理业务逻辑。
4、服务层通常由接口和实现类组成。控制器调用服务接口,而具体的业务逻辑由ServiceImpl实现类完成。
5、如果业务逻辑涉及数据库操作,服务层会调用数据访问层(DAO)。DAO层负责与数据库交互,执行增删改查等操作。
注意:DAO层只是一个中间传递角色,它不包含业务逻辑,只负责数据的存取。
6、控制器将处理结果封装为模型数据(Model),并传递给视图解析器(ViewResolver)。
7、视图解析器根据逻辑视图名称找到对应的视图模板(如JSP、Thymeleaf等)。
8、视图模板使用模型数据生成最终的HTML页面。
注解
@Controller 注解
作用:标注该类为控制器类,用于处理HTTP请求。
使用场景:
-
传统的MVC项目中,@Controller通常与视图模板(如JSP、Thymeleaf)配合使用,返回视图名称。
-
在现代前后端分离的项目中,后端通常返回JSON数据,此时@Controller可以结合@ResponseBody使用。
@ResponseBody 注解
作用:将方法的返回值直接写入HTTP响应体中,通常用于返回JSON或XML格式的数据。
使用场景:
-
前后端分离的项目中,后端直接返回数据给前端,无需视图渲染。
-
可以写在方法上,也可以写在类上(此时表示该类所有方法的返回值都直接写入响应体)。
@RestController 注解
作用:相当于@Controller + @ResponseBody,表示该类是一个控制器,并且所有方法的返回值都直接写入响应体。
使用场景:适用于前后端分离的项目,后端直接返回JSON数据。
@RequestMapping 注解
作用:配置URL映射,将HTTP请求映射到具体的控制器方法。
使用场景:
- 可以作用于类上(表示该类所有方法的URL前缀)或方法上(表示具体的URL路径)。
- 支持多种HTTP方法(如GET、POST、PUT、DELETE等)。
@RequestParam 注解
作用:将请求参数绑定到控制器方法的参数上,适用于处理表单数据或URL查询参数。
使用场景:
- 常用于GET请求或POST请求中处理表单数据。
- 可以指定参数名称、是否必填、默认值等。
@Autowired 注解
作用:自动注入依赖,Spring容器会自动查找匹配的Bean并注入到字段、构造函数或方法中。
使用场景:用于注入服务层、数据访问层或其他组件。
@PathVariable 注解
作用:将URL路径中的占位符绑定到控制器方法的参数上。
使用场景:适用于RESTful风格的URL,如/user/{id}。
以下是一个综合使用多个注解的示例:
@RestController
@RequestMapping("/hello")
public class HelloController {
@Autowired
private UserService userService;
@RequestMapping("/whoami/{name}/{sex}")
public String hello(
@PathVariable("name") String name,
@PathVariable("sex") String sex,
@RequestParam(value = "age", defaultValue = "18") int age) {
return "Hello " + name + ", Sex: " + sex + ", Age: " + age;
}
}
函数
在Java Web开发中,函数是代码的基本组成单元。不同层次的函数(如控制器函数、服务层函数、DAO层函数)有不同的职责和设计原则。
控制器函数
控制器函数是MVC架构中的入口,负责接收HTTP请求并返回响应。
职责:
1、接收请求参数(如URL参数、表单数据、JSON数据等)。
2、调用服务层处理业务逻辑。
3、返回响应(如视图名称、JSON数据等)。
示例:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable("id") int id) {
User user = userService.getUserById(id);
return ResponseEntity.ok(user);
}
@PostMapping("/create")
public ResponseEntity<String> createUser(@RequestBody User user) {
userService.createUser(user);
return ResponseEntity.ok("User created successfully");
}
}
设计原则:
1、每个控制器函数只处理一个具体的请求。
2、控制器函数应尽量简洁,复杂的业务逻辑应交给服务层处理。
3、对请求参数进行校验,确保数据的合法性。
服务层函数
服务层函数是业务逻辑的核心,负责处理具体的业务规则和流程。
职责:
1、实现业务逻辑(如数据验证、计算、流程控制等)。
2、调用DAO层与数据库交互。
3、处理事务管理(如使用@Transactional注解)。
示例:
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Override
@Transactional
public User getUserById(int id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException("User not found"));
}
@Override
@Transactional
public void createUser(User user) {
if (userRepository.existsByEmail(user.getEmail())) {
throw new DuplicateUserException("Email already exists");
}
userRepository.save(user);
}
}
设计原则:
1、每个服务函数应专注于一个具体的业务功能。
2、服务函数应尽量减少与其他模块的依赖。
3、涉及数据库操作的函数应使用事务管理,确保数据一致性。
DAO层函数
DAO(Data Access Object)层函数负责与数据库交互,执行增删改查等操作。
职责:
-
执行数据库操作(如查询、插入、更新、删除)。
-
封装数据库访问细节,提供简单的接口供服务层调用。
示例:
// 使用 @Repository 注解标记该接口为 Spring 的数据访问层(DAO)组件。
// Spring 会自动扫描并管理该接口的实现。
@Repository
// UserRepository 接口继承自 JpaRepository,提供了基本的 CRUD 操作。
// JpaRepository<User, Integer> 表示该仓库操作的是 User 实体类,且主键类型为 Integer。
public interface UserRepository extends JpaRepository<User, Integer> {
// 根据用户 ID 查询用户信息。
// 返回一个 Optional<User> 对象,避免空指针异常。
Optional<User> findById(int id);
// 检查数据库中是否存在指定邮箱的用户。
// 返回一个布尔值,true 表示存在,false 表示不存在。
boolean existsByEmail(String email);
// 使用自定义的 JPQL 查询语句,查询年龄大于指定值的用户列表。
// @Query 注解用于定义 JPQL 查询。
// :age 是命名参数,通过 @Param 注解与方法参数绑定。
@Query("SELECT u FROM User u WHERE u.age > :age")
List<User> findUsersOlderThan(@Param("age") int age);
}
设计原则:
1、每个DAO函数只负责一个具体的数据库操作。
2、DAO函数应尽量简洁,避免复杂的业务逻辑。
3、注意SQL语句的性能优化,避免全表扫描等低效操作。
数据常见处理方法
不可信数据是指来自外部、可能包含恶意内容的输入,例如用户提交的表单数据、URL参数以及第三方 API 返回的数据。因此,需要谨慎编写针对数据的处理方法。
常见场景:
1、用户输入的表单数据
2、URL参数
3、文件上传
4、请求体数据
常见的获取数据方法:
| 方法 | 说明 |
|---|---|
getParameter | 获取请求参数值 |
getParameterNames | 获取所有参数名 |
getParameterValues | 获取某个参数的所有值 |
getParameterMap | 获取参数的键值对映射 |
getQueryString | 获取 URL 查询字符串 |
getHeader | 获取指定的 HTTP 请求头 |
getHeaderNames | 获取所有请求头名称 |
getRequestURI | 获取请求的 URL |
getCookies | 获取 Cookie 信息 |
getRequestedSessionId | 获取 Session ID |
getInputStream | 以流的方式读取请求体数据 |
getReader | 以字符流的方式读取请求内容 |
getMethod | 获取请求方法(如 GET、POST) |
getProtocol | 获取请求协议 |
getServerName | 获取服务器名称 |
getRemoteUser | 获取当前缓存的用户 |
getUserPrincipal | 获取用户身份信息 |
在处理不可信数据时,必须进行严格的校验和过滤,以防止安全漏洞(如 SQL 注入、XSS 攻击等):
1、对输入数据进行严格校验(如正则匹配、白名单限制)。
2、采用安全的解析方式,避免直接拼接用户输入内容。
3、使用安全编码(如 HTML 转义)来防范 XSS 攻击。
不可信文件访问及安全防范
在处理不可信文件时,需要谨慎编写针对文件的处理方法,确保文件路径和内容的安全性,以防范路径遍历攻击、恶意文件上传等风险。
常见文件操作方法:
| 方法 | 说明 |
|---|---|
java.io.FileInputStream | 读取文件内容(字节流) |
java.io.FileOutputStream | 写入文件内容(字节流) |
java.io.FileReader | 读取文件内容(字符流) |
java.io.FileWriter | 写入文件内容(字符流) |
安全处理原则:
1、进行路径校验,确保访问的文件路径在允许的范围内,避免目录遍历漏洞(如 ../../../etc/passwd)。
2、严格校验文件扩展名、MIME 类型及文件内容,防止上传恶意脚本文件(如 .jsp、.php)。
3、在处理上传文件时,使用临时目录存储并验证后再移动,降低风险。
1万+

被折叠的 条评论
为什么被折叠?



