我正在编写一个 servlet,它将根据一些用户可定义的规则有条件地修改 HTTP 标头。(编辑:这些规则在启动时读取的 XML 文件中定义。)例如,如果响应标头不存在,则将“X-UA-Compatible: IE=edge,chrome=1”添加到响应标头中,并且如果请求指定了与已知模式匹配的“User-Agent”标头。没有更好的想法,我尝试制作自己的 POJO 来代表这些规则。它“有效”,但我觉得必须有一种更标准或更灵活的方式来做到这一点。
是否有可以解决此问题的通用库或工具(无论是内置的还是第三方的)?我听说过并读过一些关于“规则引擎”的内容,但它们似乎是更复杂/繁重的工具,不适用于像我这样简单的问题。
为了说明我正在尝试做的事情,我创建了一个简化的程序,该程序根据“条件”将“规则”应用于数字,例如“是偶数”。在这里,抱歉有点长。
主.java
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");
}
}
条件.java
package my.example.conditions;
public interface Condition<T> {
boolean appliesTo(T obj);
}
常量条件.java
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;
}
}
NumberIsEvenCondition.java
package my.example.conditions;
public class NumberIsEvenCondition implements Condition<Integer> {
@Override
public boolean appliesTo(Integer i) {
return (i % 2 == 0);
}
}
规则.java
package my.example.rules;
public interface Rule<T> {
T apply(T target);
}
抽象规则.java
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);
}
AddNumberRule.java
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;
}
}
MultiplyNumberRule.java
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;
}
}