J'aimerais pouvoir modifier/configurer les filtres d'une manière différente de web.xml. Voici une configuration statique de 2 filtres. J'aimerais pouvoir avoir un filtre configuré statiquement et permettre à ce filtre de charger des filtres supplémentaires. Je voulais juste savoir si quelqu'un connaissait la lib qui avait déjà ça.
Utilisation de l'API Servlet 2.5
<web-app>
...
<filter>
<filter-name>MyFilter1</filter-name>
<filter-class>com.me.MyFilter1</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
<filter>
<filter-name>MyFilter2</filter-name>
<filter-class>com.me.MyFilter2</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
</web-app>
J'ai vu cela fait dans Guice avec GuiceFilter où les filtres sont configurés au moment de l'exécution.
Faites simplement le même travail que le conteneur. C'est à dire. réinventer la roue du modèle de conception chaîne de responsabilité tel qu'il est sous les couvercles utilisés par les filtres de servlet.
public class GodFilter implements Filter {
private Map<Pattern, Filter> filters = new LinkedHashMap<Pattern, Filter>();
@Override
public void init(FilterConfig config) throws ServletException {
Filter1 filter1 = new Filter1();
filter1.init(config);
filters.put(new Pattern("/foo/*"), filter1);
Filter2 filter2 = new Filter2();
filter2.init(config);
filters.put(new Pattern("*.bar"), filter2);
// ...
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest hsr = (HttpServletRequest) request;
String path = hsr.getRequestURI().substring(hsr.getContextPath().length());
GodFilterChain godChain = new GodFilterChain(chain);
for (Entry<Pattern, Filter> entry : filters.entrySet()) {
if (entry.getKey().matches(path)) {
godChain.addFilter(entry.getValue());
}
}
godChain.doFilter(request, response);
}
@Override
public void destroy() {
for (Filter filter : filters.values()) {
filter.destroy();
}
}
}
avec ces petites classes auxiliaires (qui peuvent si nécessaire être faites private static
classes imbriquées des GodFilter
ci-dessus):
public class Pattern {
private int position;
private String url;
public Pattern(String url) {
this.position = url.startsWith("*") ? 1
: url.endsWith("*") ? -1
: 0;
this.url = url.replaceAll("/?\\*", "");
}
public boolean matches(String path) {
return (position == -1) ? path.startsWith(url)
: (position == 1) ? path.endsWith(url)
: path.equals(url);
}
}
et
public class GodFilterChain implements FilterChain {
private FilterChain chain;
private List<Filter> filters = new ArrayList<Filter>();
private Iterator<Filter> iterator;
public GodFilterChain(FilterChain chain) {
this.chain = chain;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
if (iterator == null) {
iterator = filters.iterator();
}
if (iterator.hasNext()) {
iterator.next().doFilter(request, response, this);
} else {
chain.doFilter(request, response);
}
}
public void addFilter(Filter filter) {
if (iterator != null) {
throw new IllegalStateException();
}
filters.add(filter);
}
}
Si nécessaire, vous pouvez également alimenter un fichier de configuration XML avec tous les filtres possibles afin de vous retrouver avec une configuration plus facile. Vous pouvez utiliser la réflexion pour créer des filtres dans init()
de votre GodFilter
.
Oh peu importe, c'est ce que le web.xml
Et le conteneur font déjà ...
Servlet 3.0 a le @WebFilter
annotation pour définir un filtre. Plus besoin de le déclarer dans web.xml.
Mais le chargement d'un filtre à partir d'un filtre n'est pas pris en charge. Vous pouvez le mettre en œuvre vous-même: c'est "juste" le modèle de chaîne de responsabilité, mais pourquoi le feriez-vous?
Il peut être réalisé en quelques étapes simples, même pour les spécifications de servlet antérieures à la 3.0:
Réf: Xstream utilise le même type de modèle pour Serializer, mais pas avec Servlet/Filter. :)