我正在编写一个servlet,它将根据一些用户可定义的规则有条件地修改HTTP头.(编辑:这些规则在启动时读取的XML文件中定义.)例如,如果响应标头尚不存在,则将"X-UA-Compatible:IE = edge,chrome = 1"添加到响应标头中如果请求指定了与已知模式匹配的"User-Agent"标头.没有任何更好的想法,我试图让我自己的POJO代表这些规则.它"有效"但我觉得必须有更标准或更灵活的方法来做到这一点.
是否有可以解决此问题的通用库或工具(无论是内置程序还是第三方)?我已经听过并读过一些关于"规则引擎"的内容,但它们似乎是更复杂/更重的工具,并不像我的那样简单.
为了说明我正在尝试做什么,我创建了一个简化程序,根据"条件"(例如"是偶数")将"规则"应用于数字.在这里,对不起它有点冗长.
package my.example;
import java.util.*;
import my.example.conditions.*;
import my.example.rules.*;
public class Main {
public static void main(String args[]) {
// Some sample objects to evaluate
Collection<Integer> numbers = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8);
print(numbers);
// Define rules
Collection<Rule<Integer>> rules = new ArrayList<Rule<Integer>>();
rules.add(createRuleToMultiplyEvenNumbersBy4());
rules.add(createRuleToAdd1ToEveryNumber());
// Process the rules for each sample object
Collection<Integer> newNumbers = new ArrayList<Integer>();
for (Integer number : numbers) {
Integer newNumber = number;
for (Rule<Integer> rule : rules)
newNumber = rule.apply(newNumber);
newNumbers.add(newNumber);
}
print(newNumbers);
}
private static Rule<Integer> createRuleToMultiplyEvenNumbersBy4() {
MultiplyNumberRule rule = new MultiplyNumberRule(true, 4);
rule.addCondition(new NumberIsEvenCondition());
return rule;
}
private static Rule<Integer> createRuleToAdd1ToEveryNumber() {
AddNumberRule rule = new AddNumberRule(true, 1);
rule.addCondition(new ConstantCondition<Integer>(true));
return rule;
}
private static void print(Collection<Integer> numbers) {
System.out.print("Numbers: ");
for (Integer number : numbers) {
System.out.print(number);
System.out.print(" ");
}
System.out.print("\r\n");
}
}
Run Code Online (Sandbox Code Playgroud)
package my.example.conditions;
public interface Condition<T> {
boolean appliesTo(T obj);
}
Run Code Online (Sandbox Code Playgroud)
package my.example.conditions;
public class ConstantCondition<T> implements Condition<T> {
private boolean constant;
public ConstantCondition(boolean alwaysReturnThisValue) {
constant = alwaysReturnThisValue;
}
@Override
public boolean appliesTo(T target) {
return constant;
}
}
Run Code Online (Sandbox Code Playgroud)
package my.example.conditions;
public class NumberIsEvenCondition implements Condition<Integer> {
@Override
public boolean appliesTo(Integer i) {
return (i % 2 == 0);
}
}
Run Code Online (Sandbox Code Playgroud)
package my.example.rules;
public interface Rule<T> {
T apply(T target);
}
Run Code Online (Sandbox Code Playgroud)
package my.example.rules;
import java.util.*;
import my.example.conditions.Condition;
public abstract class AbstractRule<T> implements Rule<T> {
private Collection<Condition<T>> conditions;
private boolean requireAllConditions;
public AbstractRule(boolean requireAllConditions) {
conditions = new ArrayList<Condition<T>>();
this.requireAllConditions = requireAllConditions;
}
public void addCondition(Condition<T> condition) {
conditions.add(condition);
}
@Override
public T apply(T target) {
boolean isApplicable;
if (requireAllConditions)
isApplicable = allConditionsSatisfied(target);
else
isApplicable = atLeastOneConditionSatisfied(target);
if (isApplicable)
target = process(target);
return target;
}
// Check if all conditions are met
protected boolean allConditionsSatisfied(T target) {
for (Condition<T> condition : conditions) {
if (!condition.appliesTo(target))
return false;
}
return true;
}
// Check if any conditions are met
protected boolean atLeastOneConditionSatisfied(T target) {
for (Condition<T> condition : conditions) {
if (condition.appliesTo(target))
return true;
}
return false;
}
abstract T process(T target);
}
Run Code Online (Sandbox Code Playgroud)
package my.example.rules;
public class AddNumberRule extends AbstractRule<Integer> {
private Integer addend;
public AddNumberRule(boolean requireAllConditions) {
this(requireAllConditions, 0);
}
public AddNumberRule(boolean requireAllConditions, Integer addend) {
super(requireAllConditions);
this.addend = addend;
}
@Override
public Integer process(Integer i) {
return i + addend;
}
}
Run Code Online (Sandbox Code Playgroud)
package my.example.rules;
public class MultiplyNumberRule extends AbstractRule<Integer> {
private Integer factor;
public MultiplyNumberRule(boolean requireAllConditions) {
this(requireAllConditions, 1);
}
public MultiplyNumberRule(boolean requireAllConditions, Integer factor) {
super(requireAllConditions);
this.factor = factor;
}
@Override
public Integer process(Integer i) {
return i * factor;
}
}
Run Code Online (Sandbox Code Playgroud)
好吧,我会使用Commons Chain
用于组织复杂处理流程的执行的一种流行技术是“责任链”模式,如经典的“四人帮”设计模式书中所描述的(以及许多其他地方)。尽管实现此设计模式所需的基本 API 合约非常简单,但拥有一个有助于使用该模式的基本 API 非常有用,并且(更重要的是)鼓励来自多个不同来源的命令实现的组合。
这是一种常见的设计模式,猜测适合您的问题