假设我已经定义了这些RESTendpoint:
@RequestMapping(path = "/user")
@RestController
public class ConfigUserController {
[...]
@GetMapping(path = "/variables/")
public ResponseEntity<List<Variable>> getAllVariables(...)
[...]
}
@GetMapping(path = "/variables/{name}")
public ResponseEntity<Variable> getVariableByName(...)
[...]
}
@PutMapping(path = "/variables/{name}/{value}")
public ResponseEntity<Variable> setVariableByName(...)
[...]
}
}
我定义了两个过滤器(日志记录和授权),在这些过滤器中,我想获得与当前请求匹配的url模式。使用上述示例:
基本上,我需要的是在我的过滤器的doFilter(ServletRequest-request-request,ServletResponse-response,FilterChain-chain)方法中获得映射注释中定义的路径。
理想情况下,我希望能够访问我的过滤器中的url模式值,如下所示:
@Component
@Order(3)
public class MyAuthorizationRequestFilter extends GenericFilterBean {
[...]
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// here I get the value
String urlPattern = request.useSomeMethod().toGetUrlPattern();
[...]
boolean auth = false;
// here I do stuff
[...]
// finally let's see if the user is authorized
if (auth) {
chain.doFilter(request, responde);
} else {
throw SomeAuthorizationError();
}
}
[...]
}
我一直在寻找,但我找不到一个可行的解决方案。
如果可能的话,我宁愿不扫描集合或web.xml文件(我没有),也不使用反射,因为每次触发过滤器时都会执行代码,我不想影响性能。
欢迎链接或建议。
编辑:添加详细信息,添加过滤器示例cose
过滤器在请求到达DispatcherServlet之前拦截请求,使其成为粗粒度任务的理想选择,例如:
注意*在尝试调用getAttribute之前,先执行doFilter
您的控制器
@RequestMapping(path = "/user")
@RestController
public class ConfigUserController {
@GetMapping(path = "/variables/")
public ResponseEntity<List<Variable>> getAllVariables() {
return null;
}
@GetMapping(path = "/variables/{name}")
public ResponseEntity<Variable> getVariableByName(@PathVariable("name") String name) {
return new ResponseEntity<Variable>(new Variable(name), HttpStatus.OK);
}
@PutMapping(path = "/variables/{name}/{value}")
public ResponseEntity<Variable> setVariableByName() {
return null;
}
}
定制过滤器
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO
try {
chain.doFilter(request, response);
} catch (Exception e) {
} finally {
String pattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
System.out.println("Request template is, " + pattern);
}
}
}
订单号:
Request template is, /user/variables/{name}
HandlerIntercepors拦截DispatcherServlet和我们的控制器之间的请求。这是在Spring MVC框架内完成的,它提供了对处理程序和ModelAndView对象的访问。
自定义拦截器
@Component
public class LoggerInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception arg3)
throws Exception {
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView model)
throws Exception {
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
String path = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
System.out.println("path : " + path);
return true;
}}
向InterceptorRegistry注册
@Component
public class CustomServiceInterceptorAppConfig implements WebMvcConfigurer {
@Autowired
LoggerInterceptor loggerInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loggerInterceptor);
}
}
单例作用域并设置为预实例化(默认)的Bean是在创建容器时创建的。这是一个一次性过程,您不必担心性能。
您可以预扫描所有@RequestMapping、@GetMapping、@PostMApping等。。注释,保留它,然后在过滤器中匹配模式以获得所需的结果。
这是样品
豆
@Configuration
public class Config {
@Bean
public List<String> getPatterns() throws ClassNotFoundException {
List<String> str = new ArrayList<String>();
Class clazz = Class.forName("com.example.demo.controller.ConfigUserController"); // or list of controllers,
// //you can iterate that
// list
for (Method method : clazz.getMethods()) {
for (Annotation annotation : method.getDeclaredAnnotations()) {
if (annotation.toString().contains("GetMapping")) {
str.add(annotation.toString());
System.out.println("Annotation is..." + annotation.toString());
}
if (annotation.toString().contains("PutMapping")) {
str.add(annotation.toString());
System.out.println("Annotation is..." + annotation.toString());
}
if (annotation.toString().contains("PostMapping")) {
str.add(annotation.toString());
System.out.println("Annotation is..." + annotation.toString());
}
}
}
return str;
}
定制过滤器
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomFilter implements Filter {
@Autowired
Config con;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO
try {
//filter match the pattern to get the desired result
System.out.println(con.getPatterns());
} catch (ClassNotFoundException e) {
}
chain.doFilter(request, response);
}
更新答案以使用GenericFilterBean。根据提出的问题进行筛选。可以通过添加finally子句来实现这一点。这是必需的,因为您需要执行链。doFilter(请求,响应)首先调用请求。getAttribute,因为该属性直到请求生命周期的后期才设置。因此,如果您试图基于传入的uri模板执行某些操作,那么在这里子类化GenericFilterBean可能不是正确的选择,因为您需要调用chain。先进行doFilter。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
//Do something
chain.doFilter(request, response);
} finally {
String pathTemplate = (String)
request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
System.out.println("Incoming Request path Template from Generic Filter : " + pathTemplate);
}
}
替代选项:
假设您在这里使用的是Spring Web。您可以定义一个HandlerInterceptor
并将其注册到Interceptor注册表
。
@Component
public class LogPathTemplateInterceptor
implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
String pathTemplate = (String)request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
System.out.println("Incoming Request path Template : " + pathTemplate);
return true;
}
}
定义完后,向InterceptorRegistry注册它。查看如何将路径模式添加到拦截器。
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private LogPathTemplateInterceptor logInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(logInterceptor)
.addPathPatterns("/variables/**");
}
}
这应该记录请求模板路径,而不是带有变量的路径。
问题内容: 我对创建一个可以接受金额,ISO 4217货币代码和小数大小并以该格式返回金额的过滤器感兴趣。我注意到AngularJS在中,但是我对Angular比较陌生,不知道是否可以使用它? 问题答案: 货币模式和符号就是这样。它确定如何显示数字。它将不会从XXX转换为XXX。您将必须根据当前的转换率进行转换。 至于使用内置货币格式,有多种方法:在模板中,在代码中。 在模板中: 在代码中: 在这
问题内容: 我定义了一个,并且具有带有Spring注释的Java类。 我想将Bean 放入我的,因此尝试了以下操作: 但是它总是返回。我怎样才能得到一个Spring bean? 问题答案: 尝试: 你的bean在应用程序上下文中的名称/标识在哪里。甚至更好: 还可以看看GenericFilterBean及其子类。
主要内容:实现,Person.java,Criteria.java,CriteriaMale.java,CriteriaFemale.java,CriteriaSingle.java,AndCriteria.java,OrCriteria.java,CriteriaPatternDemo.java过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型
过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。 实现 我们将创建一个 Person 对象、Criteria 接口和实现了该接口的实体类,来过滤 Person 对象的列表。CriteriaP
过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。 实现 我们将创建一个 Person 对象、Criteria 接口和实现了该接口的实体类,来过滤 Person 对象的列表。CriteriaP
我正在处理一个安全过滤器,它需要根据path变量的值做一些检查。我试着这样做: 但映射始终为空,因此我的筛选器的优先级似乎高于在请求中填充属性的。 我已尝试添加以下配置: 这没有帮助,筛选器是在调用之前执行的。 在我的安全过滤器中,我获取Auth头,解密它,从中获取并将它与路径var值进行比较。如果这些ID不匹配,我返回403。 我想知道是否有可能覆盖这两个动作的顺序。或者,也许,有其他的方法来检