RESTful intermediate path solution based on SpringMVC backend system

RESTful intermediate path solution based on SpringMVC backend system

background

In order to standardize and version control, the current industry generally prefers to add intermediate paths such as /api/{version} in URL design based on RESTful style design.

However , SpringMVC does not provide and support such requirements by default. Of course, this problem can be solved by configuring context in a very simple Servlet container (such as tomcat ) . But this will inevitably affect the flexibility of deployment.

To this end, like this type of design, try to achieve the following design goals and requirements:

1) The intermediate path is transparent to the Servlet container;

2) The intermediate path is transparent to business development;

3) Support {version} dynamically configurable; (It is recommended to configure the service version number under the api project classpath path, such as: support.auth.api.version=v1 )

 

Implementation plan

Based on the OCP design ideas of Spring and SpringMVC , we can easily extend and realize our own special business requirements without destroying the business processing of the original framework.

 

Currently, it is mainly implemented by extending RequestMappingHandlerMapping . For details, please refer to the attached code.

 

package com.lachesis.support.auth.demo.handler;

import java.lang.reflect.Method;

import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

public class PrefixEnabledRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
	public static final String URL_SLASH = "/";

	private String contextPrefix;

	protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
		RequestMappingInfo info = super.getMappingForMethod(method, handlerType);

		RequestMappingInfo prefixedInfo = null;
		if (info != null) {
			PatternsRequestCondition patt = info.getPatternsCondition();
			String[] prefixedPatts = prefixPatterns(patt.getPatterns().toArray(new String[patt.getPatterns().size()]));
			PatternsRequestCondition patternsCondition = new PatternsRequestCondition(prefixedPatts,
					this.getUrlPathHelper(), this.getPathMatcher(), this.useSuffixPatternMatch(),
					this.useTrailingSlashMatch(), this.getFileExtensions());
			prefixedInfo = new RequestMappingInfo(info.getName(), patternsCondition, info.getMethodsCondition(),
					info.getParamsCondition(), info.getHeadersCondition(), info.getConsumesCondition(),
					info.getProducesCondition(), info.getCustomCondition());
		}
		return prefixedInfo;
	}

	public String getContextPrefix() {
		return contextPrefix;
	}

	public void setContextPrefix(String contextPrefix) {
		this.contextPrefix = contextPrefix;
	}

	protected String[] prefixPatterns(String[] patts) {
		if (patts == null) {
			return null;
		}
		String[] prefixedPatts = new String[patts.length];
		for (int i = 0; i < patts.length; i++) {
			if (patts[i].startsWith(URL_SLASH)) {
				prefixedPatts[i] = getContextPrefix() + patts[i];
			} else {
				prefixedPatts[i] = getContextPrefix() + URL_SLASH + patts[i];
			}
		}
		return prefixedPatts;
	}
}

 In the configuration, reference the custom handlerrmapping

<context:property-placeholder
		location="classpath:support-auth-demo-version.properties"
		ignore-unresolvable="true" />
	<bean id="handlerMapping"
		class="com.lachesis.support.auth.demo.handler.PrefixEnabledRequestMappingHandlerMapping">
		<property name="contextPrefix" value="/api/${support.auth.demo.version}"/>
	</bean>
	<context:component-scan base-package="com.lachesis.support.auth.demo.controller" />
	<mvc:annotation-driven />

 

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326815337&siteId=291194637