Skip to content

Instantly share code, notes, and snippets.

@xuanyu-h
Last active April 1, 2020 08:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xuanyu-h/3dcf8f2573c90746f605854136b16f0d to your computer and use it in GitHub Desktop.
Save xuanyu-h/3dcf8f2573c90746f605854136b16f0d to your computer and use it in GitHub Desktop.
import xxx.xxx.xxx.StringUtil;
import org.springframework.core.annotation.Order;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author xuanyu on 2020/3/16
* <p>
* This filter contains two functions(For compatibility with the older Rails versions).
* It means every request via the GET method, which has query parameters, will do this filter.
* <p>
* 1. Convert the SORT params, e.g., /?sort=views_count,asc will converted to /?sort=viewsCount,asc
* <p>
* 2. Convert the key of the query parameters, e.g., /?user_id=1 will converted to /?userId=1
*/
@Component
@Order(1)
public class SnakeCaseConverterFilter extends OncePerRequestFilter {
// DON'T CHANGE SpringDataWebProperties.Sort.sortParameter
private static final String SORT_PARAMETER = "sort";
private static final String SORT_DELIMITER = ",";
private static final String HTTP_METHOD = "GET";
@Override
protected void doFilterInternal(@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain) throws ServletException, IOException {
if (shouldApply(request)) {
filterChain.doFilter(new SnakeCaseConverterRequestWrapper(request), response);
} else {
filterChain.doFilter(request, response);
}
}
protected boolean shouldApply(HttpServletRequest request) {
return request.getMethod().equals(HTTP_METHOD) && request.getQueryString() != null;
}
protected static class SnakeCaseConverterRequestWrapper extends HttpServletRequestWrapper {
private final Map<String, String[]> parameters = new ConcurrentHashMap<>();
/**
* Constructs a request object wrapping the given request.
*
* @param request The request to wrap
* @throws IllegalArgumentException if the request is null
*/
public SnakeCaseConverterRequestWrapper(HttpServletRequest request) {
super(request);
for (String param : request.getParameterMap().keySet()) {
if (StringUtil.shouldConvert(param)) {
parameters.put(StringUtil.snakeCaseToCamelCase(param), request.getParameterValues(param));
}
parameters.put(param, request.getParameterValues(param));
}
}
@Override
public String getParameter(final String name) {
if (!parameters.containsKey(name)) {
return null;
}
String value = parameters.get(name)[0];
if (name.equals(SORT_PARAMETER)) {
return StringUtil.snakeCaseToCamelCase(value, SORT_DELIMITER);
}
return value;
}
@Override
public Enumeration<String> getParameterNames() {
return Collections.enumeration(parameters.keySet());
}
@Override
public Map<String, String[]> getParameterMap() {
return parameters;
}
@Override
public String[] getParameterValues(final String name) {
String[] values = parameters.get(name);
if (name.equals(SORT_PARAMETER) && !ObjectUtils.isEmpty(values)) {
String[] finalValues = new String[values.length];
for (int i = 0; i < values.length; i++) {
finalValues[i] = StringUtil.snakeCaseToCamelCase(values[i], SORT_DELIMITER);
}
return finalValues;
}
return values;
}
}
}
@xuanyu-h
Copy link
Author

xuanyu-h commented Apr 1, 2020

import org.apache.commons.text.CaseUtils;

import javax.validation.constraints.NotNull;

/**
 * @author xuanyu on 2020/3/11
 */
public class StringUtil {

    private static final Character SNAKE_DELIMITER = '_';

    public static Boolean shouldConvert(@NotNull String string) {
        return string.indexOf(SNAKE_DELIMITER) >= 0;
    }

    public static String snakeCaseToCamelCase(@NotNull String string) {
        if (!shouldConvert(string)) {
            return string;
        }

        return CaseUtils.toCamelCase(string, false, SNAKE_DELIMITER);
    }

    public static String snakeCaseToCamelCase(@NotNull String string, @NotNull String splitDelimiter) {
        StringBuilder builder = new StringBuilder();
        String[] parts = string.split(splitDelimiter);

        int index = 0;
        for (String part : parts) {
            ++index;
            builder.append(snakeCaseToCamelCase(part)).append(index < parts.length ? splitDelimiter : "");
        }

        return builder.toString();
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment