采用Java编写TinyWeb
Java版的TinyWeb是一个采用传统的面向对象风格编写的基本MVC Web框架.我们使用控制器处理请求,该控制器是使用模板方法模式实现的,采用策略模式实现视图.
核心的数据结构有HttpRequest和HttpResponse,具有不可变性,并且使用生成器模式创建这些对象.
过滤器是在请求被处理之前运行的,他会对请求进行操作.我们使用Filter类是想过滤器.
整个系统概况如下:
HttpRequest和HttpResponse
使用生成器模式创建HTTPRequest和httpResponse:
public class HttpResponse{
private final String body;
private final Integer responseCode;
public String getBody() {
return body;
}
public Integer getResponseCode() {
return responseCode;
}
private HttpResponse(Builder builder){
body = builder.body;
responseCode = builder.responseCode;
}
public static class Builder {
private String body;
private String responseCode;
public Builder body(String body){
this.body = body;
return this;
}
public Builder responseCode(Integer responseCode){
this.responseCode = responseCode;
return this;
}
public HttpResponse build() {
return HttpResponse(this);
}
public static Builder newBuilder() {
return new Bulider();
}
}
}
这种方式将全部的可变性封装在一个Builder对象,该对象将会用来创建不可变的HTTPResponse,比如我们创建一个简单的测试请求:
HttpResponse testResponse = HttpResponse.Builder.newBuilder()
.responseCode(200)
.body("responseBody")
.build();
如果不适用Builder,我们需要将所有需要的参数传递给构造器.
在HttpRequest中,为了支持请求过滤器对传入请求的修改,需要创建一个机遇当前请求对象的新请求,我们将使用buildFrom()来实现,该方法将一个现成的HttpRequest作为入参,并使用它来设置新builder的初始值:
public static Builder builderFrom(HttpRequest request){
Builder builder = new Builder();
builder.path(request.getPaty());
builder.body(request.getBody());
Map<String,String> headers = request.getHeaders();
for (String headerName : headers.keySet())
builder.addHeader(headerName, headers.get(headerNmae));
return builder();
}
视图和策略模式
首先我们需要一个view接口,它拥有一个唯一的方法render().render方法以类型Map
import java.util.List;
import java.util.Map;
public interface View{
public String render(Map<String, List<String>> model);
}
然后实现两个类,StrategyView和RenderingStrategy,这两个类被设计用来共同实现策略模式.
RenderingStrategy负责完成实际的视图渲染工作,它将由框架的用户负责实现,下面是策略模式中策略类的一个实例:
public interface RenderingStrategy{
public String renderView(Map<String, List<String>> model);
}
然后是RenderingStrategy的代理类StrategyView,该类由框架实现,并负责对RenderingStrategy抛出的异常进行处理:
public class StrategyView implements View {
private RenderingStrategy viewRenderer;
public StrategyView(RenderingStrategy viewRenderer){
this.viewRenderer = viewRenderer;
}
@override
public String render(Map<String, List<String>> model){
try {
return viewRenderer.renderView(model);
} catch (Exception e){
throw new RenderingException(e);
}
}
}
….