目录
pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Controller
package dr.cqr.controller;
import dr.cqr.config.UserInfo;
import dr.cqr.vo.Search;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import static java.lang.Thread.sleep;
@RestController
@RequestMapping("/test")
public class Test {
@GetMapping("/t")
public String tt () throws InterruptedException {
sleep(10000);
System.out.println(UserInfo.get("token"));
System.out.println(UserInfo.get("name"));
return "ok";
}
// @RequestMapping:
// 是一个通用注解,可用于处理所有HTTP方法(GET、POST、PUT、DELETE等)。
// 需要通过method属性显式指定HTTP方法。否则默认处理所有方法。
// @RequestMapping(value = "/request_mapping_get", method = RequestMethod.GET)
@RequestMapping(value = "/request_mapping_get", method = {RequestMethod.GET, RequestMethod.POST})
public String RequestMappingGet () {
return "request_mapping_get";
}
// @PostMapping
// @GetMapping
// @PutMapping
// @DeleteMapping
// @PatchMapping
@GetMapping("/get_mapping_get")
public String GetMappingGet () {
return "get_mapping_get";
}
// 路径变量与参数 路径上不能设置可选
@GetMapping("/get_mapping_get/{id}/{name}")
public String GetMappingGetId (@PathVariable Long id,
@PathVariable(value = "name", required = false) String name) {
System.out.println(id);
System.out.println(name);
return "ok";
}
// 请求参数处理
// 使用@RequestParam获取查询参数(如?name=John)
// 使用@RequestBody和@ResponseBody处理JSON/XML等格式。
@PostMapping("/search")
public String Search (@RequestParam String name,
@RequestParam(value = "email", required = false, defaultValue = "ff@123") String emails,
@RequestParam(value = "sex", required = false, defaultValue = "1") String sex,
@RequestHeader(value = "token", required = false, defaultValue = "") String token,
Search search // form-data x-www-from-urlencode
) {
System.out.println(name);
System.out.println(emails);
System.out.println(sex);
System.out.println(token);
System.out.println(search);
return "ok";
}
@PostMapping(value = "/search2", consumes = "application/json")
public String Search2 (@RequestParam String name,
@RequestParam(value = "email", required = false, defaultValue = "ff@123") String emails,
@RequestHeader(value = "token", required = false, defaultValue = "") String token,
@RequestBody(required = false) Search search // raw
) {
System.out.println(name);
System.out.println(emails);
System.out.println(token);
System.out.println(search);
return "ok";
}
// 单文件上传 form-data
@PostMapping("/upload")
public String handleFileUpload(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return "File is empty";
}
try {
byte[] bytes = file.getBytes();
// 处理文件字节流,例如保存到磁盘或数据库等
System.out.println(file.getOriginalFilename());
System.out.println(new String(bytes));
return "File uploaded successfully";
} catch (IOException e) {
return "Failed to upload file";
}
}
// 多文件上传 form-data
@PostMapping("/uploadMultiple")
public String handleMultipleFileUpload(HttpServletRequest request) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
List<MultipartFile> files = multipartRequest.getFiles("files"); // 假设表单字段名为files,且可以上传多个文件。注意这里是复数形式。
if (files == null || files.isEmpty()) {
return "No files uploaded";
} else {
return "Files uploaded successfully: " + files.stream()
.map(MultipartFile::getOriginalFilename) // 获取文件名列表,可以根据需要修改此部分代码以处理文件内容等。
.collect(Collectors.toList()); // 例如,转换为列表形式返回文件名。
}
}
}
WebConfig
package dr.cqr.config;
import dr.cqr.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer
.defaultContentType(MediaType.APPLICATION_JSON)
.mediaType("json", MediaType.APPLICATION_JSON)
.mediaType("xml", MediaType.APPLICATION_XML)
.mediaType("csv", MediaType.TEXT_PLAIN);
}
// 在Spring配置中注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") // 拦截所有请求,也可以指定路径模式如 "/api/**"
.excludePathPatterns("/api/ignore/**") // 排除某些路径,如忽略"/api/ignore/**"的请求
.order(0); //执行顺序
}
}
Interceptor
package dr.cqr.interceptor;
import dr.cqr.config.UserInfo;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// 拦截器
// preHandle Controller方法执行前 登录验证、参数预处理 能阻断请求
// postHandle Controller执行后视图渲染前 统一添加响应头、修改Model数据
// afterCompletion 视图渲染完成后 资源释放、日志记录
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("开始请求");
String url = request.getRequestURI();//是否是登录请求
if (url.contains("login")) {
return true;//进行放行
} else {//判断是否登录过
String token = request.getHeader("token");
System.out.println(token);
String name = request.getParameter("name");
UserInfo.set("name", name);
//response.setContentType("text/html");
//response.setCharacterEncoding("UTF-8");
//response.getWriter().println("token不存在");
//return false;
return true;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
System.out.println("结束请求1");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
System.out.println("结束请求2");
}
}
登录信息UserInfo
package dr.cqr.config;
import java.util.HashMap;
import java.util.Map;
public class UserInfo {
// ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,
// 该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。
// ThreadLocal为变量在每个线程中都创建了一个副本,
// 那么每个线程可以访问自己内部的副本变量。
// 当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都可被回收
private static final ThreadLocal<Map<String, String>> THREAD_LOCAL = new ThreadLocal<>();
//判断线程map是否为空,为空就添加一个map
public static Map<String, String> getLocalMap() {
Map<String, String> map = THREAD_LOCAL.get();
if (map == null) {
map = new HashMap<>(10);
THREAD_LOCAL.set(map);
}
return map;
}
//把用户信息添加到线程map中
public static void set(String key, String name) {
Map<String, String> map = getLocalMap();
map.put(key, name);
}
//获得线程map中的数据
public static String get(String key) {
Map<String, String> map = getLocalMap();
return map.get(key);
}
}