我遇到的问题之request method ‘post’ not supported

我遇到的问题之request method ‘post’ not supported

你所遇到的问题,别人肯定也遇到过。

背景

​ 最近在做一个后台系统的spring升级为spring boot的项目,期间各种xml配置要升级为configuration Bean的方式,还有自己公司的一些jar包升级。升级的,如果想快速搞定的,可以找别人已经尝试过上线的系统拿来参考。不过我一般不屑上面这种做法,本着学习工作,工作学习的心态,怎么可以老找捷径了,话不多说,上报错信息。
在这里插入图片描述
报405错误,请求的方法不支持“POST"请求。

熟悉的页面,不熟悉的解决办法。

尝试解决

​ 第一次尝试,方法上强制指定为POST请求。
在这里插入图片描述
​ 尝试失败,实际上springMvc未指定method时,get,post方式都可以请求进来。

​ 一时没有思路,开启“百度大法好”,搜了大片就下面一篇文章阅读数量多(潜台词,他阅读量多,他是大佬)

https://blog.csdn.net/weixin_42074868/article/details/85001093?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1

文章有图,有源码,但最终提供出来的解决办法让我无法苟同。
在这里插入图片描述

源码大法好

​ 读完这篇博文后,虽然没有解决问题,但给我提供了解决思路,就是从源码分析问题。

​ 开启断点,由上文可知,具体报错位置在WebContentGenerator.checkRequest方法的378行处,一次post请求会调用两次checkRequest()方法.

​ 第一次调用时,可以看到supportedMethods为null,跳过接着执行。
在这里插入图片描述
第二次调用时,supportedMethods集合中只包含GET,HEAD两个方法,所以报了对应的错误,然后游览器显示403。
在这里插入图片描述
​ 问题复现了,那我们该怎么接着分析问题产生的原因呢,这里我将修改supportedMethods这个集合数据的都打上了断点。
构造方法
在这里插入图片描述
在这里插入图片描述
set方法,初步怀疑是下面方法设置的两个值
在这里插入图片描述
果然在setSupportedMethods方法的调用上面,我们看到了这样一个控制器

/**
 * 平凡的控制器,总是返回一个预先配置的视图,并可以选择设置响应状态代码。可以使用以下方式配置视图和状态
提供的配置属性。
 * Trivial controller that always returns a pre-configured view and optionally
 * sets the response status code. The view and status can be configured using
 * the provided configuration properties.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Keith Donald
 * @author Rossen Stoyanchev
 */
public class ParameterizableViewController extends AbstractController {

	private Object view;

	private HttpStatus statusCode;

	private boolean statusOnly;


	public ParameterizableViewController() {
		super(false);
        //这里调用了setSupportedMethods只方法传入get head方法
		setSupportedMethods(HttpMethod.GET.name(), HttpMethod.HEAD.name());
	}

接着向上跟踪代码在ViewControllerRegistry中,看到了addViewController这样一个方法。

/**
	 * Map a view controller to the given URL path (or pattern) in order to render
	 * a response with a pre-configured status code and view.
	 * <p>Patterns like {@code "/admin/**"} or {@code "/articles/{articlename:\\w+}"}
	 * are allowed. See {@link org.springframework.util.AntPathMatcher} for more details on the
	 * syntax.
	 */
	public ViewControllerRegistration addViewController(String urlPath) {
		ViewControllerRegistration registration = new ViewControllerRegistration(urlPath);
		registration.setApplicationContext(this.applicationContext);
		this.registrations.add(registration);
		return registration;
	}

这个方法在我们系统中有使用过,还是我最近添加的。
1589009350651.png
由于我们后台系统,需要对一些url装饰,方便加上对应的head,foot固定页面资源。我原先采用了下面这篇文章,把原来的sitemesh进行了改造,这里我偷了个懒,没有单独定义一个DecoratorController写上面三个请求,而是加到了addViewControllers方法中。

spring boot整合freemarker+sitemeshhttps://www.jianshu.com/p/8484e706b5a4

重新debug

可以看到由我们的webMvcConfig类的addViewControllers方法进来的,传入了get,head。并没有post方法
在这里插入图片描述

最终default,perfrom,control三个静态的控制器注册了上去。
在这里插入图片描述
在这里插入图片描述
我们系统里面对应的post请求url都是/****/control这种,会被control这个控制器装饰,从而拦截了post请求。

public class WebSiteMeshFilter extends ConfigurableSiteMeshFilter {

    private static final String DEFAULT_URL = "/default";
    private static final String CONTROL_URL = "/control";
    private static final String PERFORM_URL = "/perform";

    @Override
    protected void  applyCustomConfiguration(SiteMeshFilterBuilder builder) {
        builder.addDecoratorPath("/*stru*", DEFAULT_URL)
                .addDecoratorPath("/*main*", DEFAULT_URL)
                .addDecoratorPath("/*/control*", CONTROL_URL)
                .addDecoratorPath("/*/perform*", PERFORM_URL)
                .addExcludedPath("**ajax=true")//不需要装饰的路径
                .addExcludedPath("/images/**")
                .addExcludedPath("/scripts/**")
                .addExcludedPath("/services/**")
                .addExcludedPath("/styles/**")
                .addExcludedPath("/statics/**")
                .addExcludedPath("/visitWeb.html");
    }
}

总结

​ 我单独定义一个DecoratorController,把静态的addViewControllers代码删除,就跑成功了。

@Controller
public class DecoratorController {

    @RequestMapping(value = "/default")
    public ModelAndView index(ModelMap modelMap) {
        return new ModelAndView("/decorators/default");
    }

    @RequestMapping(value = "/control")
    public ModelAndView control(ModelMap modelMap) {
        return new ModelAndView("/decorators/control");
    }

    @RequestMapping(value = "/perform")
    public ModelAndView perform(ModelMap modelMap) {
        return new ModelAndView("/decorators/perform");
    }
}

奇怪的知识增加了

addViewControllers中只能添加get,head请求的url,一般常用于静态的 页面。

springboot是在spring的基础上,增添了starter相应的功能和各种扩展,但其内部保存的spring功能是完整,几乎也是完全可以使用的。这么久,spring的ioc和aop功能都几乎没有改动,除了spring第五版采用了jdk8的很大书写方式。所以不要傻傻的看别人博客说springboot不支持post方法。

希望以后一切问题从实际出发,哪里出了问题,就从哪里开始分析。

尽信书不如无书

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值