拦截器和过滤器的区别:
过滤器(Filter) :可以拿到原始的http请求,但是拿不到你请求的控制器和请求控制器中的方法的信息。
拦截器(Interceptor):可以拿到你请求的控制器和方法,却拿不到请求方法的参数。
切片(Aspect): 可以拿到方法的参数,但是却拿不到http请求和响应的对象
1.过滤器和拦截器触发时机不一样,过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
2、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并管理的,spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑。而过滤器是JavaEE标准,只需依赖servlet api ,不需要依赖spring。
3、过滤器的实现基于回调函数。而拦截器(代理模式)的实现基于反射
4、Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
5、Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理(反射)的方式来执行。
6、Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。
最简单明了的区别就是过滤器可以修改request,而拦截器不能
过滤器需要在servlet容器中实现,拦截器可以适用于javaEE,javaSE等各种环境
拦截器可以调用IOC容器中的各种依赖,而过滤器不能
过滤器只能在请求的前后使用,而拦截器可以详细到每个方法
一、应用场景:
Springboot的过滤器,在web开发中可以过滤指定的url
比如过拦截掉我们不需要的接口请求,同时也可以修改request和response内容
过滤器的应用场景:
1)过滤敏感词汇(防止sql注入)
2)设置字符编码
3)URL级别的权限访问控制
4)压缩响应信息
二、实现方法:
1、使用spring boot提供的FilterRegistrationBean注册Filter
2、使用原生servlet注解定义Filter
两种方式的本质都是一样的,都是去FilterRegistrationBean注册自定义Filter
方式一: (使用spring boot提供的FilterRegistrationBean注册Filter )
①、先定义Filter:
package com.corwien.filter;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
Logger logger = LoggerFactory.getLogger(BaseFilter.class);
static final String TOKEN = "20220423344556abac";
//内部接口集合
public static List<String> INSIDE_URLS = Lists.newArrayList("/index","/inside");
//白名单接口集合
public static List<String> WHITE_PATH = Lists.newArrayList("/white","/login");
@Override public void init(FilterConfig filterConfig) throws ServletException {
}
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // do something 处理request 或response
// doFilter()方法中的servletRequest参数的类型是ServletRequest,需要转换为HttpServletRequest类型方便调用某些方法
System.out.println("filter1"); // 调用filter链中的下一个filter
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String ip = request.getRemoteAddr();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = new Date();
String date = sdf.format(d);
System.out.printf("%s %s 访问了 %s%n", date, ip, url);
String requestURI = request.getRequestURI();
if(INSIDE_URLS.contains(requestURI)){
//内部接口,直接通过
filterChain.doFilter(servletRequest,servletResponse);
return;
}
if(WHITE_PATH.contains(requestURI)){
//白名单接口,直接通过
filterChain.doFilter(servletRequest,servletResponse);
return;
}
//进行校验,如token校验
String token = request.getHeader("token");
if(TOKEN.equals(token)){
filterChain.doFilter(servletRequest,servletResponse);
}else {
//token校验不通过,重定向到登录页面
wrapper.sendRedirect("/login");
}
}
@Override public void destroy() {
}
}
过滤器需要实现Filter类,其中有三个默认的方法(init初始方法,doFilter核心过滤方法,destroy销毁方法)
②、注册自定义Filter过滤器配置类
@Configuration
public class FilterConfig {
/**
* 基础过滤器
* @return
*/
@Bean
public FilterRegistrationBean<Filter> baseFilter(){
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new BaseFilter());
filterRegistrationBean.setUrlPatterns(Lists.newArrayList("/*"));
filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
}
}
新增controller方法和登录页login.html
@RestController
public class restController {
@Autowired
private AsynService asynService;
/**
* 白名单接口
* @return
*/
@GetMapping("/while")
public String whileTest(){
return "success";
}
/**
* 非白名单接口
* @return
*/
@GetMapping("/no-while")
public String noWhileTest(){
return "success";
}
/**
* 登录接口
* @param username
* @param password
* @param mv
* @param request
* @param model
* @return
*/
@GetMapping("/login")
public ModelAndView login(String username, String password, ModelAndView mv, HttpServletRequest request, Model model){
if(StringUtils.hasLength(username)&&StringUtils.hasLength(password)){
//TODO 登录逻辑
System.out.println("成功!!");
mv.setViewName("index");
}else{
System.out.println("失败!!");
mv.setViewName("/login.html");
}
return mv;
}
}
项目启动后,访问下面两个接口(白名单接口PK非白名单接口)
接口一:http://localhost:8080/whileTest
接口二:http://localhost:8080/no-while
接口一为白名单范畴,过滤器直接通行,返回“success”
接口二在过滤器中需要校验token,在没有携带token的情况下,会重定向到登录页
是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s
我有一个名为Post的类,我需要能够适应以下场景:如果用户选择了一个类别,则只显示该类别的帖子如果用户选择了一种类型,则只显示该类型的帖子如果用户选择了一个类别和类型,则只显示该类别中该类型的帖子如果用户没有选择任何内容,则显示所有帖子我想知道我的Controller是否不可避免地会因大量条件语句而显得粗糙...这是我解决此问题的错误方法-有谁知道我如何才能做到这一点?classPostsController 最佳答案 您最好遵循“胖模型,瘦Controller”的惯例,这意味着您应该将这种逻辑放在模型本身中。Post类应该能够报告
我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?
我仍然收到标题中的“错误”消息,但不知道如何解决。在ApplicationController中,classApplicationController在routes.rb#match'set_activity_account/:id/:value'=>'users#account_activity',:as=>:set_activity_account--thisdoesn'tworkaswell..resources:usersdomemberdoget:action_a,:action_bendcollectiondoget'account_activity'endend和User
对于用户模型,我有一个过滤器来检查用户的预订状态,该状态由整数值(0、1或2)表示。UserActiveAdmin索引页上的过滤器是通过以下代码实现的:filter:booking_status,as::select然而,这会导致下拉选项为0、1或2。当管理员用户从下拉列表中选择它们时,我更愿意自己将它们命名为“未完成”、“待定”和“已确认”之类的名称。有没有办法在不改变booking_status在模型中的表示方式的情况下做到这一点? 最佳答案 假设booking_status是模型中的枚举字段,您可以使用:过滤器:booking
以下模型通过belongs_to链接:require'mongoid'classSensorincludeMongoid::Documentfield:sensor_id,type:Stringvalidates_uniqueness_of:sensor_idend...require'mongoid'require_relative'sensor.rb'classSensorDataincludeMongoid::Documentbelongs_to:sensorfield:date,type:Datefield:ozonMax1h,type:Floatfield:ozonMax8h
我在RubyonRails4.1.4上有一个项目,使用来自git://github.com/activeadmin/activeadmin的activeadmin1.0.0.pre,pg0.17.1,PostgreSQL9.3在项目中我有这些模型:类用户has_one:账户类账户属于:用户有很多:project_accountshas_many:项目,:through=>:project_accounts类项目#该项目有一个bool属性'archive'has_many:project_accounts类ProjectAccount属于:帐户属于:项目我有一个任务是在索引页面上实现一个
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我正在寻找一种在Rails中进行协作过滤的解决方案,甚至是可能的示例。到目前为止,我只发现了acts_as_recommendable,它看起来很有用,但我注意到它在过去2年中没有任何更新。有人知道任何其他解决方案和/或示例吗?
我对Jekyll和Ruby很陌生(但是,非常兴奋)。在不使用插件的情况下,我试图找到一种方法来过滤site.related_posts。例如,我正在阅读标题为Foo且类别为A、B的帖子。该站点总共包含3个帖子:Foo(类别:A、B)条形图(类别:A、C、D)动物园(类别:B、F)默认情况下,在Jekyll中我们这样做:{%forpostinsite.related_postslimit:5%}{%endfor%}但是,上面的代码返回所有(3)个帖子。一个帖子包含很多类别,所以类别应该是一个数组。如何修改代码并仅返回类别与当前帖子类别相交的类别?(在此示例中,我希望代码仅返回Foo和Zo
我允许用户在我的网站上上传文件。其中一些文件可能非常大,占用了我的大量日志文件。所以我不想让它出现。我知道:config.filter_parameters+=[:password]过滤某些参数。但问题是它的参数是这样的散列:{:person=>{:name=>'bob',:file=>{:data=>'reallylongdata.thiscanbetensofthousandsofcharacterslong'}}}我可以将:data添加到filter_parameters,但这会在整个站点中隐藏大量日志,因为数据是一个公共(public)键(我也无法将其重命名为更模糊的名称)。f