Springboot2之静态资源规则与定制化welcome与favicon功能Rest映射及源码解析以及改变默认的_method

Posted 爱上口袋的天空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Springboot2之静态资源规则与定制化welcome与favicon功能Rest映射及源码解析以及改变默认的_method相关的知识,希望对你有一定的参考价值。

一、静态资源规则与定制化

1、静态资源目录

只要静态资源放在类路径下: called /static (or /public or /resources or /META-INF/resources

访问 : 当前项目根路径/ + 静态资源名

原理: 静态映射/**

请求进来,先去找Controller看能不能处理。不能处理的所有请求又都交给静态资源处理器。静态资源也找不到则响应404页面

也可以改变默认的静态资源路径,/static,/public,/resources, /META-INF/resources失效

resources:
  static-locations: [classpath:/haha/]

2、静态资源访问前缀

spring:
  mvc:
    static-path-pattern: /res/**

当前项目 + static-path-pattern + 静态资源名 = 静态资源文件夹下找

3、webjar

可用jar方式添加css,js等资源文件,

WebJars - Web Libraries in Jars

例如,添加jquery

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.5.1</version>
</dependency>

访问地址:http://localhost:8080/webjars/jquery/3.5.1/jquery.js 后面地址要按照依赖里面的包路径。


二、web场景-welcome与favicon功能

1、欢迎页支持

  • 静态资源路径下 index.html

    • 可以配置静态资源路径
    • 但是不可以配置静态资源的访问前缀。否则导致 index.html不能被默认访问
spring:
#  mvc:
#    static-path-pattern: /res/**   这个会导致welcome page功能失效
  resources:
    static-locations: [classpath:/haha/]
  • controller能处理/index。

2、自定义Favicon

指网页标签上的小图标。

favicon.ico 放在静态资源目录下即可。

spring:
#  mvc:
#    static-path-pattern: /res/**   这个会导致 Favicon 功能失效

三、Rest映射及源码解析

1、请求映射

  • @xxxMapping;
    • @GetMapping
    • @PostMapping
    • @PutMapping
    • @DeleteMapping
  • Rest风格支持(使用HTTP请求方式动词来表示对资源的操作)
    • 以前:
      • /getUser 获取用户
      • /deleteUser 删除用户
      • /editUser 修改用户
      • /saveUser保存用户
    • 现在: /user
      • GET-获取用户
      • DELETE-删除用户
      • PUT-修改用户
      • POST-保存用户
    • 核心Filter;HiddenHttpMethodFilter
  • 用法
    • 开启页面表单的Rest功能
    • 页面 form的属性method=post,隐藏域 _method=put、delete等(如果直接get或post,无需隐藏域)
    • 编写请求映射
spring:
  mvc:
    hiddenmethod:
      filter:
        enabled: true   #开启页面表单的Rest功能
<form action="/user" method="get">
    <input value="REST-GET提交" type="submit" />
</form>

<form action="/user" method="post">
    <input value="REST-POST提交" type="submit" />
</form>

<form action="/user" method="post">
    <input name="_method" type="hidden" value="DELETE"/>
    <input value="REST-DELETE 提交" type="submit"/>
</form>

<form action="/user" method="post">
    <input name="_method" type="hidden" value="PUT" />
    <input value="REST-PUT提交"type="submit" />
<form>
@GetMapping("/user")
//@RequestMapping(value = "/user",method = RequestMethod.GET)
public String getUser()
    return "GET-张三";


@PostMapping("/user")
//@RequestMapping(value = "/user",method = RequestMethod.POST)
public String saveUser()
    return "POST-张三";


@PutMapping("/user")
//@RequestMapping(value = "/user",method = RequestMethod.PUT)
public String putUser()
    return "PUT-张三";


@DeleteMapping("/user")
//@RequestMapping(value = "/user",method = RequestMethod.DELETE)
public String deleteUser()
    return "DELETE-张三";

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

	private static final List<String> ALLOWED_METHODS =
			Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(),
					HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));

	/** Default method parameter: @code _method. */
	public static final String DEFAULT_METHOD_PARAM = "_method";

	private String methodParam = DEFAULT_METHOD_PARAM;


	/**
	 * Set the parameter name to look for HTTP methods.
	 * @see #DEFAULT_METHOD_PARAM
	 */
	public void setMethodParam(String methodParam) 
		Assert.hasText(methodParam, "'methodParam' must not be empty");
		this.methodParam = methodParam;
	

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException 

		HttpServletRequest requestToUse = request;

		if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) 
			String paramValue = request.getParameter(this.methodParam);
			if (StringUtils.hasLength(paramValue)) 
				String method = paramValue.toUpperCase(Locale.ENGLISH);
				if (ALLOWED_METHODS.contains(method)) 
					requestToUse = new HttpMethodRequestWrapper(request, method);
				
			
		

		filterChain.doFilter(requestToUse, response);
	


	/**
	 * Simple @link HttpServletRequest wrapper that returns the supplied method for
	 * @link HttpServletRequest#getMethod().
	 */
	private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper 

		private final String method;

		public HttpMethodRequestWrapper(HttpServletRequest request, String method) 
			super(request);
			this.method = method;
		

		@Override
		public String getMethod() 
			return this.method;
		
	


  • Rest使用客户端工具。
    • 如PostMan可直接发送put、delete等方式请求。

四、请求处理-【源码分析】-怎么改变默认的_method

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass( Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class )
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter( DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
		ValidationAutoConfiguration.class )
public class WebMvcAutoConfiguration 

    ...
    
    @Bean
    @ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
    @ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false)
    public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() 
        return new OrderedHiddenHttpMethodFilter();
    
    
    ...

    

 @ConditionalOnMissingBean(HiddenHttpMethodFilter.class)意味着在没有HiddenHttpMethodFilter时,才执行hiddenHttpMethodFilter()。因此,我们可以自定义filter,改变默认的_method。例如:

@Configuration(proxyBeanMethods = false)
public class WebConfig
    //自定义filter
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter()
        HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
        methodFilter.setMethodParam("_m");
        return methodFilter;
        

_method改成_m

<form action="/user" method="post">
    <input name="_m" type="hidden" value="DELETE"/>
    <input value="REST-DELETE 提交" type="submit"/>
</form>

创作打卡挑战赛 赢取流量/现金/CSDN周边激励大奖

以上是关于Springboot2之静态资源规则与定制化welcome与favicon功能Rest映射及源码解析以及改变默认的_method的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 2从入门到入坟 | Web场景开发篇:静态资源规则与定制化

Spring Boot 2从入门到入坟 | Web场景开发篇:静态资源规则与定制化

SpringBoot2之web开发(上)——之静态资源和请求参数处理

SpringBoot2---静态资源映射规则

SpringBoot03_静态资源访问请求参数处理

SpringBoot:静态资源映射定制404配置icon