Springboot 2.x系列文章5-WEB开发2-动态访问



前言

Springboot 开发,最常用的就是WEB项目动态访问开发


一、新旧动态访问变化

  • Rest风格支持(使用HTTP请求方式动词来表示对资源的操作)
    — 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户
    — 现在: /user GET-查询/获取用户 DELETE-删除用户 PUT-修改用户 POST-新增/保存用户

二、method方法介绍

1.CreateXXX-post

HTML前端

 <form action="/user" method="post">
     <input value="rest-post" type="submit" />
 </form>

Controller接口后端

    @RequestMapping(value = "/user",method = RequestMethod.POST)
    public String PostUser()
    {
        return "张三-Post";
    }

2. DeleteXXX-delete

HTML前端

  • 正常理解method=“delete”,但是method只有get和post;不支持(需修改)
<form action="/user" method="delete">
    <input value="rest-delete" type="submit">
</form>
  • 修改为post方法,加上method,delete协助
 <form action="/user" method="post">
     <input name="_method" type="hidden" value="delete"/>
     <input value="rest-update" type="submit">
 </form>

Controller接口后端

    @RequestMapping(value = "/user",method = RequestMethod.DELETE)
    public String DeleteUser()
    {
        return "张三-delete";
    }

3. UpdateXXX-put

  • 正常理解,但是method只有get和post,不支持put
 <form action="/user" method="PUT">
     <input value="rest-update" type="submit">
 </form>
  • 修改为post方法,加上method,put协助
 <form action="/user" method="post">
     <input name="_method" type="hidden" value="PUT"/>
     <input value="rest-update" type="submit">
 </form>

Controller接口后端

    @RequestMapping(value = "/user",method =RequestMethod.PUT)
    public String UpdateUser()
    {
        return "张三-update";
    }

4.Query-get

HTML前端

<form action="/user" method="get">
   <input value="rest-get" type="submit" />
</form>

Controller接口后端

    @RequestMapping(value = "/user",method = RequestMethod.GET)
    public String GetUser()
    {
        return "张三-Get";
    }

5. 增加put和delete支持

修改yaml文件

  mvc:
    hiddenmethod:
      filter:
        enabled: true

原理

  • WebMvcAutoConfiguration(OrderedHiddenHttpMethodFilter)
  • OrderedHiddenHttpMethodFilter
  • HiddenHttpMethodFilter( _method 和 post)
  • HttpMethodRequestWrapper(内部类)
    命令集合 ALLOWED_METHODS = HttpMethod.PUT、DELETE.name(), PATCH.name())
public class HiddenHttpMethodFilter extends OncePerRequestFilter {
    private static final List<String> ALLOWED_METHODS;
    public static final String DEFAULT_METHOD_PARAM = "_method";
    private String methodParam = "_method";
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        HttpServletRequest requestToUse = request;
        if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) {
            String paramValue = request.getParameter(this.methodParam);
            if (StringUtils.hasLength(paramValue)) {
                String method = paramValue.toUpperCase(Locale.ENGLISH);
                if (ALLOWED_METHODS.contains(method)) {
                    requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
                }
            }
        }

        filterChain.doFilter((ServletRequest)requestToUse, response);
    }

自定义参数名,增加请求方法

如修改为“FuMethod”

  • 由配置可知,当不存在时使用默认的,那么自定义即先加载一个自定义的HiddenHttpMethodFilter类
    @Bean
    @ConditionalOnMissingBean({HiddenHttpMethodFilter.class})
    @ConditionalOnProperty(
        prefix = "spring.mvc.hiddenmethod.filter",
        name = {"enabled"}
    )
    public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
        return new OrderedHiddenHttpMethodFilter();
    }
  • 自定义一个HiddenHttpMethodFilter类
@Configuration
public class MyFilterConfig {
    @Bean
    public HiddenHttpMethodFilter MyHiddenHttpMethodFilter()
    {
        HiddenHttpMethodFilter myMethodFilter=new HiddenHttpMethodFilter();
        myMethodFilter.setMethodParam("_FuMethod");
        return myMethodFilter;
    }

}

三、rest请求映射原理

任何调用后端的方法都要经过doDispatch

  • DispatchServlet的类继承关系
    在这里插入图片描述
  • 常用方法及实现类
    在这里插入图片描述

doGet方法调用顺序

  • HttpServlet的doGet
  • FrameworkServlet的processRequest
  • DispatchServlet的doService
  • DispatchServlet的doDispatch
    在这里插入图片描述

doDispatch方法解读

  • 获取request
  • 处理文件上传
  • 找到request对应处理方法mappedHandler(controller的方法)
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				// 找到当前请求使用哪个Handler(Controller的方法)处理
				mappedHandler = getHandler(processedRequest);
                
                //HandlerMapping:处理器映射。/xxx->>xxxx

常见HandlerMappings

所有的请求映射都在HandlerMapping中,如下图所示。

  • SpringBoot自动配置欢迎页的 WelcomePageHandlerMapping 。访问 /能访问到index.html;
  • SpringBoot自动配置了默认 的 RequestMappingHandlerMapping
  • 请求进来,挨个尝试所有的HandlerMapping看是否有请求信息。
    ○ 如果有就找到这个请求对应的handler
    ○ 如果没有就是下一个 HandlerMapping
  • 我们需要一些自定义的映射处理,我们也可以自己给容器中放HandlerMapping。自定义 HandlerMapping
    在这里插入图片描述

四、注意事项

Form表单提交

Rest原理(表单提交要使用REST的时候)

  • 表单提交会带上_method=PUT
  • 请求过来被HiddenHttpMethodFilter拦截
    ○ 请求是否正常,并且是POST
    ■ 获取到_method的值。
    ■ 兼容以下请求;PUT.DELETE.PATCH
    ■ 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
    ■ 过滤器链放行的时候用wrapper。

yaml配置文件

  mvc:
    hiddenmethod:
      filter:
        enabled: true

客户端工具

  • Rest使用客户端工具,无需设置Filter。
    如PostMan(JMeter)直接发送Put、delete等方式请求,无需Filter。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值