SpringBoot-Web开发之请求参数处理

注解获取参数

  1. 常用注解
  • @PathVariable:获取restful方式的请求参数
  • @RequestHeader:获取http请求的header部分信息
  • @RequestAttribute:获取域中数据
  • @RequestParam:获取请求体的key-value 参数
  • @MatrixVariable:请求路径中,分号前为路径,获取分号后的请求参数
  • @CookieValue:获取cookie信息
  • @RequestBody:获取整个请求体中的数据
  • 更多可查看参数解析器-HandlerMethodArgumentResolver
java 复制代码
@RestController
public class ParameterTestController {

    //  car/2/owner/zhangsan
    //cookie的key值在控制台查看请求头
    @GetMapping("/car/{id}/owner/{username}")
    public Map<String,Object> getCar(@PathVariable("id") Integer id,
            @PathVariable("username") String name,
            @PathVariable Map<String,String> pv,
			@RequestHeader("User-Agent") String userAgent,
			@RequestHeader Map<String,String> header,
			@RequestParam("age") Integer age,
			@RequestParam("inters") List<String> inters,
			@RequestParam Map<String,String> params,
			@CookieValue("_ga") String _ga,
			@CookieValue("_ga") Cookie cookie){

        Map<String,Object> map = new HashMap<>();
        map.put("_ga",_ga);
        return map;
    }

    @PostMapping("/save")
    public Map postMethod(@RequestBody String content){
        Map<String,Object> map = new HashMap<>();
        map.put("content",content);
        return map;
    }


    //1、语法: 请求路径:/cars/sell;low=34;brand=byd,audi,yd
    //2、SpringBoot默认是禁用了矩阵变量的功能
    //      手动开启:原理。对于路径的处理。UrlPathHelper进行解析。
    //              removeSemicolonContent(移除分号请求内容)
    //3、矩阵变量必须有url路径变量才能被解析
    @GetMapping("/cars/{path}")
    public Map carsSell(@MatrixVariable("low") Integer low,
                        @MatrixVariable("brand") List<String> brand,
                        @PathVariable("path") String path){
        
		Map<String,Object> map = new HashMap<>();
        map.put("low",low);
        map.put("brand",brand);
        map.put("path",path);
        return map;
    }

    // /boss/1;age=20/2;age=10
    @GetMapping("/boss/{bossId}/{empId}")
    public Map boss(
			@MatrixVariable(value = "age",pathVar = "bossId") Integer bossAge,
            @MatrixVariable(value = "age",pathVar = "empId") Integer empAge){

        Map<String,Object> map = new HashMap<>();
        map.put("bossAge",bossAge);
        map.put("empAge",empAge);
        return map;
    }

}

@Controller
public class RequestController {
	
	@GetMapping("/goto")
    public String goToPage(HttpServletRequest request){

        request.setAttribute("msg","成功了...");
        request.setAttribute("code",200);
        return "forward:/success";  //转发到  /success请求
    }

	@ResponseBody
	@GetMapping("/success")
	public Map success(
				@RequestAttribute(value = "msg",required = false) String msg,
				@RequestAttribute(value = "code",required = false)Integer code,
				HttpServletRequest request){
		
		Object msg1 = request.getAttribute("msg");
		Map<String,Object> map = new HashMap<>();
		return map;
	}
}
  1. 开启矩阵变量功能
  • 方法一:配置类实现接口WebMvcConfigurer,重写方法configurePathMatch
java 复制代码
@Configuration(proxyBeanMethods = false)
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {

        UrlPathHelper urlPathHelper = new UrlPathHelper();
        //默认true移除支持矩阵变量,故需设为false
        // 不移除;后面的内容。矩阵变量功能就可以生效
        urlPathHelper.setRemoveSemicolonContent(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
}
  • 方法二:自定义WebMvcConfigurer的组件
java 复制代码
//WebMvcConfigurer定制化SpringMVC的功能
@Bean
public WebMvcConfigurer webMvcConfigurer(){
	return new WebMvcConfigurer() {

		@Override
		public void configurePathMatch(PathMatchConfigurer configurer) {
			UrlPathHelper urlPathHelper = new UrlPathHelper();
			// 不移除;使矩阵变量功能生效
			urlPathHelper.setRemoveSemicolonContent(false);
			configurer.setUrlPathHelper(urlPathHelper);
		}
	};
}

Servlet API获取参数

  • WebRequest、ServletRequest、MultipartRequest、 HttpSession 等等......
  • ServletRequestMethodArgumentResolver类
  • 也是存在参数解析器-HandlerMethodArgumentResolver
java 复制代码
@Override
public boolean supportsParameter(MethodParameter parameter) {
	Class<?> paramType = parameter.getParameterType();
	return (WebRequest.class.isAssignableFrom(paramType) ||
			ServletRequest.class.isAssignableFrom(paramType) ||
			MultipartRequest.class.isAssignableFrom(paramType) ||
			HttpSession.class.isAssignableFrom(paramType) ||
			(pushBuilder != null && pushBuilder.isAssignableFrom(paramType)) ||
			Principal.class.isAssignableFrom(paramType) ||
			InputStream.class.isAssignableFrom(paramType) ||
			Reader.class.isAssignableFrom(paramType) ||
			HttpMethod.class == paramType ||
			Locale.class == paramType ||
			TimeZone.class == paramType ||
			ZoneId.class == paramType);
}

复杂参数

  • Map、Model(map、model里面的数据会被放在request的请求域==request.setAttribute)
  • Errors/BindingResult
  • RedirectAttributes( 重定向携带数据)
  • ServletResponse(response)
java 复制代码
@GetMapping("/params")
public String testParam(Map<String,Object> map,
						Model model,
						HttpServletRequest request,
						HttpServletResponse response){
	
	map.put("hello","world666");
	model.addAttribute("world","hello666");
	request.setAttribute("message","HelloWorld");
	Cookie cookie = new Cookie("c1","v1");
	response.addCookie(cookie);
	return "forward:/success";
}

@ResponseBody
@GetMapping("/success")
public Map success(@RequestAttribute(value = "msg",required = false) String msg,
				   @RequestAttribute(value = "code",required = false)Integer code,
				   HttpServletRequest request){
	Object msg1 = request.getAttribute("msg");

	Map<String,Object> map = new HashMap<>();
	Object hello = request.getAttribute("hello");
	Object world = request.getAttribute("world");
	Object message = request.getAttribute("message");
	return map;
}

参数处理过程

  • 从DispatcherServlet类中doDispatch()开始
  1. HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler())
  • HandlerMapping中找到能处理请求的Handler(Controller.method())
  • 为当前Handler 找一个适配器 HandlerAdapter; RequestMappingHandlerAdapter
  • 适配器执行目标方法并确定方法参数的每一个值
  1. mv = ha.handle(processedRequest, response, mappedHandler.getHandler())
  • 执行目标方法,RequestMappingHandlerAdapter类的handleInternal()
  • mav = this.invokeHandlerMethod(request, response, handlerMethod)
  1. 参数解析器-HandlerMethodArgumentResolver
  • RequestMappingHandlerAdapter类的invokeHandlerMethod()
  • 确定将要执行的目标方法的每一个参数的值是什么
  • SpringMVC目标方法能写多少种参数类型。取决于参数解析器,当前2.3.4版本查看26种。
  • 当前解析器是否支持解析这种参数,支持就调用 resolveArgument()
  1. 返回值处理器
  • RequestMappingHandlerAdapter类的invokeHandlerMethod()
  • 当前2.3.4版本查看15种
  1. RequestMappingHandlerAdapter类的invokeHandlerMethod()
  • invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0])
  • 进入方法,ServletInvocableHandlerMethod类的invokeAndHandle()
  • 进入方法,InvocableHandlerMethod类的invokeForRequest()
  1. InvocableHandlerMethod类的getMethodArgumentValues()
  • 获取到Controller方法上的每一个参数信息
  • 使用的参数注解,参数类型等等
  • 循环所有参数解析器判断Controller参数的注解是否有对应解析器
    • HandlerMethodArgumentResolverComposite类的getArgumentResolver()
  • 循环解析获取每一个参数的值
    • AbstractNamedValueMethodArgumentResolver类的resolveArgument()
  1. 自定义类型参数,封装的POJO
  • ServletModelAttributeMethodProcessor ,这个参数处理器支持解析
  • 会判断当前类型是否为简单类型
  • WebDataBinder:web数据绑定器,利用它里面的 Converters 将请求数据转成指定的数据类型,封装到JavaBean中
  • GenericConversionService:在设置每一个值的时候,找它里面的所有converter将这个数据类型(request带来参数的字符串)转换到指定的类型
  1. 自定义 Converter作类型转换用
  • 只能针对form表单提交数据,不能在restfulApi下生效
java 复制代码
@Bean
public WebMvcConfigurer webMvcConfigurer(){
	return new WebMvcConfigurer() {

		@Override
		public void addFormatters(FormatterRegistry registry) {
            //自定义转换类型
			registry.addConverter(new Converter<String, Pet>() {

				@Override
				public Pet convert(String source) {
					// source获取到的请求内容
					if(!StringUtils.isEmpty(source)){
						Pet pet = new Pet();
						String[] split = source.split(",");
						pet.setName(split[0]);
						pet.setAge(Integer.parseInt(split[1]));
						return pet;
					}
					return null;
				}
			});
		}
	};
}
相关推荐
新建文件夹-4 小时前
深入浅出Langchain4j——构建Java大语言模型应用的新范式
java·开发语言·语言模型
絔宝4 小时前
Eclipse控制台乱码解决方式
java·ide·eclipse
小白银子4 小时前
零基础从头教学Linux(Day 55)
java·linux·服务器·python
不爱编程的小九九5 小时前
小九源码-springboot097-java付费自习室管理系统
java·开发语言·spring boot
兜兜风d'5 小时前
Spring Boot 整合 RabbitMQ :四大核心模式解析
spring boot·rabbitmq·java-rabbitmq
独自破碎E5 小时前
LeetCode 381: O(1) 时间插入、删除和获取随机元素 - 允许重复
java·算法·leetcode
程语有云5 小时前
生产事故-Caffeine缓存误用之临下班的救赎
java·缓存·caffeine·阻塞·log·生产事故
Miraitowa_cheems5 小时前
LeetCode算法日记 - Day 81: 最大子数组和
java·数据结构·算法·leetcode·决策树·职场和发展·深度优先
CodeCraft Studio5 小时前
国产化Word处理控件Spire.Doc教程:用Java实现TXT文本与Word互转的完整教程
java·c#·word·spire.doc·word文档转换·txt转word·word转txt