And*_*row 7 java freemarker jersey dropwizard
我正在阅读https://jersey.github.io/documentation/latest/filters-and-interceptors.html和http://www.dropwizard.io/1.1.4/docs/manual/core.html#jersey-过滤器尝试使这个:
@CookieParam("User-Data") userData: String,
@HeaderParam("User-Agent") userAgent: String,
Run Code Online (Sandbox Code Playgroud)
我的网络应用程序的每个资源GET方法都不需要.userData
是来自cookie的json数据,其中包含"name"和"id"等字段,并且userAgent
是标题中的完整User-Agent字符串.对于我传入的每个视图:
AppUser.getName(userData), AppUser.isMobile(userAgent)
Run Code Online (Sandbox Code Playgroud)
该getName
函数解析json并仅返回name字段,isMobile
如果找到字符串"mobile" ,函数将返回true布尔值.
我在FreeMarker中的应用程序的每个视图中使用它来显示用户的名字,并在移动设备为真时更改一些布局内容.
有没有办法减少重复次数?我宁愿每次都使用BeforeFilter来自动设置它.
听起来像你可以在a中做的事情,在视图资源/控制器返回后ContainerResponseFilter
调用.假设你返回,你得到的从,从它那里得到的模型,并添加额外的信息模型.Viewable
Viewable
ContainerRequestContext#getEntity
@Provider
@UserInModel
public class UserInModelFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext request,
ContainerResponseContext response) throws IOException {
Cookie cookie = request.getCookies().get("User-Data");
String header = request.getHeaderString("User-Agent");
String username = AppUser.getName(cookie.getValue());
boolean isMobile = AppUser.isMobile(header);
Viewable returnViewable = (Viewable) response.getEntity();
Map<String, Object> model = (Map<String, Object>) returnViewable.getModel();
model.put("username", username);
model.put("isMobile", isMobile);
}
}
Run Code Online (Sandbox Code Playgroud)
该@UserInModel
注释是一个自定义的名称绑定注解,这是用来确定哪些资源类或方法应该通过这个过滤器.由于您不希望所有端点都通过此过滤器,因此只需注释所需的方法或类.
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface UserInModel {
}
@Path("/")
public class IndexController {
@GET
@UserInModel
@Produces(MediaType.TEXT_HTML)
public Viewable home() {
Map<String, Object> model = new HashMap<>();
return new Viewable("/index", model);
}
}
Run Code Online (Sandbox Code Playgroud)
使用Dropwizard,您只需注册过滤器即可.
env.jersey().register(UserInModelFilter.class);
Run Code Online (Sandbox Code Playgroud)
如果要在调用资源方法之前对cookie和标头进行一些预处理,则可以在a中执行此操作,ContainerRequestFilter
也可以使用名称绑定.而不是AppUser.xxx
在响应过滤器中重新计算方法,您也可以只设置一个属性,ContainerRequestContext#setProperty
以后可以从getProperty
响应过滤器中的相同上下文()中检索该属性.
上面的答案假设您正在使用Jersey的MVC支持,因此使用Viewable
.如果你使用Dropwizard的视图支持,那么它没有太大的不同.您可能希望创建一个抽象类作为所有视图类的父类,这样您就可以在从过滤器中检索实体时转换为抽象类型.
public class AbstractView extends View {
private String userName;
private boolean isMobile;
protected AbstractView(String templateName) {
super(templateName);
}
public String getUserName() { return userName; }
public void setUserName(String userName) { this.userName = userName; }
public boolean isMobile() { return isMobile; }
public void setIsMobile(boolean mobile) { isMobile = mobile; }
}
public class PersonView extends AbstractView {
private final Person person;
public PersonView(Person person) {
super("person.ftl");
this.person = person;
}
public Person getPerson() {
return this.person;
}
}
Run Code Online (Sandbox Code Playgroud)
在过滤器中
@Provider
@UserInModel
public class UserInModelFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext request,
ContainerResponseContext response) throws IOException {
Cookie cookie = request.getCookies().get("User-Data");
String header = request.getHeaderString("User-Agent");
String username = AppUser.getName(cookie.getValue());
boolean isMobile = AppUser.isMobile(header);
AbstractView returnViewable = (AbstractView) response.getEntity();
returnViewable.setUserName(username);
returnViewable.setIsMobile(isMobile);
}
}
Run Code Online (Sandbox Code Playgroud)
已完成测试的资源类
@Path("person")
public class PersonController {
@GET
@UserInModel
@Produces(MediaType.TEXT_HTML)
public PersonView person() {
Person person = new Person("peeskillet@fake.com");
return new PersonView(person);
}
}
Run Code Online (Sandbox Code Playgroud)