Я думаю, что для этого нельзя использовать web.xml
. Тем не менее, вы можете выполнить то, что вам нужно, закодировав свой класс MyFilter
, чтобы вам не нужно было его изменять при добавлении новой страны.
Я вижу, что вы используете Весну. Это хорошая новость, так как MyFilter
на самом деле является фасолью, управляемой весной. Это означает, что к нему могут быть добавлены другие бобы. Мое предложение состоит в том, что у вас есть один компонент для каждой страны и один основной фильтр, на который будет поручено делегировать правильную страну.
Во-первых, пусть ваш web.xml
как сейчас:
<filter>
<filter-name>myfilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>myfilter</filter-name>
<url-pattern>*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
Это позволит боб с именем myfilter
вызывается для каждого запроса.
Затем осуществить MyFilter
таким образом, что это страна-агностик, так что не нужно быть изменен, когда страна добавлены или удалены:
@Component("myfilter")
public class MyFilter implements Filter {
public static final String DEFAULT = "default";
public static final String SUFFIX = "_Filter";
// Autowire all beans that implement CountryFilter, mapped by bean name
@Autowired
private Map<String, CountryFilter> filters;
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// Get country code from request
Locale locale = request.getLocale();
String countryCode = locale.getCountry().toUpperCase();
// Format key to gey country-specific filter
String key = countryCode + SUFFIX;
// If bean doesn't exist for request country...
if (!this.filters.containsKey(key)) {
// ..fallback to default filter
key = DEFAULT + SUFFIX;
}
// Get filter for country
CountryFilter filter = this.filters.get(key);
// Delegate to actual country (or default) filter
boolean countinueChain = filter.doFilterForCountry(request, response);
if (continueChain) {
chain.doFilter(request, response);
}
}
@Override
public void init(FilterConfig config) throws ServletException {
}
@Override
public void destroy() {
}
}
Этот класс достаточно универсален. Вам не нужно менять его при добавлении или удалении страны. Хитрость заключается в том, чтобы использовать поведение Autowower Spring для коллекций. Если вы запустили autowire Map<String, T>
, то Spring заполнит эту карту всеми экземплярами фасонов класса T
, являющимися ключами, равными именам компонентов и значениями соответствующих экземпляров компонента.
Затем вам нужно интерфейс CountryFilter
:
public interface CountryFilter {
boolean doFilterForCountry(ServletRequest request, ServletResponse response)
throws IOException, ServletException;
}
Вы должны были бы осуществить CountryFilter
для каждой страны, позволяя ей быть Spring боб, чье имя соответствует шаблону CC_Filter
, где CC
обозначает 2-значный код страны ISO. Например, для США вы можете иметь:
@Component("US" + MyFilter.SUFFIX)
public class UsFilter implements CountryFilter {
@Override
public boolean doFilterForCountry(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
// TODO Handle US specifics here
// VERY IMPORTANT: you might want to let the chain continue...
return true;
// ...or redirect to US page
// ((HttpServletResponse) response).sendRedirect("US-url");
// return false;
// ONLY ONE of the options!
}
}
И для Великобритании:
@Component("UK" + MyFilter.SUFFIX)
public class UkFilter implements CountryFilter {
@Override
public boolean doFilterForCountry(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
// TODO Handle UK specifics here
// VERY IMPORTANT: you might want to let the chain continue...
return true;
// ...or redirect to UK page
// ((HttpServletResponse) response).sendRedirect("UK-url");
// return false;
// ONLY ONE of the options!
}
}
То же самое для других стран.
Наконец, может случиться так, что у вас нет реализации для данной страны. В этом случае, вы можете иметь фильтр по умолчанию в качестве запасного варианта корпуса:
@Component(MyFilter.DEFAULT + MyFilter.SUFFIX)
public class DefaultFilter implements CountryFilter {
@Override
public boolean doFilterForCountry(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
// TODO Handle DEFAULT specifics here
// VERY IMPORTANT: you might want to let the chain continue...
return true;
// ...or redirect to DEFAULT page
// ((HttpServletResponse) response).sendRedirect("DEFAULT-url");
// return false;
// ONLY ONE of the options!
}
}
Надеется, что это поможет вам решить вашу проблему. Я считаю, что это довольно гибкий подход, у него даже есть резервный случай. Чтобы добавить новую страну, все, что вам нужно сделать, это реализовать новый CountryFilter
.
У вас есть страна в URL? Вы можете сопоставить фильтр в 'web.xml' по шаблону url. В противном случае вам нужно будет выполнить нужную логику внутри 'MyFilter'. –
В URL-адресе я не могу иметь страну, но jsp может передать ее как параметр. Как сопоставить их в файле web.xml? –
Вы не отображаете это в файле 'web.xml', но внутри вашего фильтра, с кодом. –