有时候需要知道拦截Guice中方法调用的方法拦截器的顺序.一个简单的示例场景是使用guice-persist提供的@Transactional方法拦截器和自定义的@Retry方法拦截器.重试拦截器必须在事务拦截器之外运行,以确保重试不在同一事务中执行.
在Spring中,您可以使用拦截器的Ordered接口来确保在重试拦截器中执行事务拦截器.有没有办法在Guice中实现同样的目标?
我正在使用OkHttp和Retrofit来制作我的应用程序的网络请求.我还使用拦截器进行身份验证,并在必要时重试请求.
服务器有时会出现临时问题,并返回空体,尽管响应状态为200 OK.这会导致我的应用程序崩溃,因为调用了Retrofit Callback的成功块,返回(并使用GSON解析)的自定义对象为null,成功回调中的代码假定返回一个对象.
我已经向服务器团队报告了这个问题,但我也想修复它,而不必使用null检查将所有成功回调代码包装在应用程序上.
Currenty我倾向于两个选项,虽然任何其他想法都是最受欢迎的:1)不从拦截器返回(这甚至可能吗?)并且只显示一个错误对话框2)返回一些会使Retrofit调用失败的部分打回来.
我的代码如下.正如您所看到的,当收到空体时,我会重试该请求最多3次.
@Override
public Response intercept(Chain chain) throws IOException
{
// First
Request request = chain.request();
Response response = chain.proceed(request);
....
....
....
// Retry empty body response requests for a maximum of 3 times
Integer retryMaxCount = 3;
MediaType contentType = response.body().contentType();
String bodyString = response.body().string();
while (bodyString.length() == 0 && retryMaxCount > 0)
{
//Empty body received!, Retrying...
retryMaxCount--;
response = chain.proceed(request);
bodyString = response.body().string();
}
if (bodyString.length() != 0)
{
// Create …Run Code Online (Sandbox Code Playgroud) 出于学习目的,我制作了一个自定义身份验证系统,我通过Authorization标头将令牌从客户端传递到服务器。
在服务器端,我想知道是否可以在拦截器中创建,在请求到达控制器中的方法之前,一个 User 对象,以来自令牌的电子邮件作为属性,然后将此用户对象传递给我需要的每一个请求。
这就是我想得到的,例如:
@RestController
public class HelloController {
@RequestMapping("/")
public String index(final User user) {
return user.getEmail();
}
}
public class User {
private String email;
}
Run Code Online (Sandbox Code Playgroud)
其中user是我使用请求Authorization标头在预拦截器中创建的对象,然后我可以传递或不传递给RestController.
这可能吗?
我目前正在学习Struts 2,目前我正在构建一个简单的应用程序,其中未经验证的用户被重定向到登录表单.
我有一个登录表单和操作功能,它获取用户凭据,验证它们并在会话中存储User对象但是我现在试图阻止在登录之前访问页面并且我试图用拦截器执行此操作.
我的问题是我编写了一个拦截器,用于检查User对象是否已保存在会话中,但如果没有,我想重定向到登录页面,并且无法绕过struts并使用HttpServletResponse.sendRedirect方法
组态:
<package name="mypackage" extends="struts-default" namespace="/admin">
<interceptors>
<interceptor name="login" class="my.LoginInterceptor" />
</interceptors>
<default-interceptor-ref name="login"/>
<action name="login" class="my.LoginAction">
<result name="input">/admin/login.jsp</result>
<result name="success" type="redirect">/admin</result>
</action>
<action name="private" class="my.PrivateAction">
<result>/admin/private.jsp</result>
</action>
</package>
Run Code Online (Sandbox Code Playgroud)
拦截器代码:
@Override
public String intercept(ActionInvocation inv) throws Exception {
Map<String, Object> session = inv.getInvocationContext().getSession();
Object user = session.get("user");
if(user == null) {
// redirect to the 'login' action here
}
else {
return inv.invoke();
}
}
Run Code Online (Sandbox Code Playgroud) 我知道可以在方法调用之前使用@AroundInvoke注释来使用拦截器.
我想要做的是在方法调用之后执行某些代码,这样我就可以在方法执行之前和之后创建一个日志条目.
这可能是EJB3,还是我需要使用AOP?
我正在尝试设置rails应用程序,以便我可以在不同的邮件传递方法之间进行选择,具体取决于某些条件是否为真.
所以,给出两种交付方式:
ActionMailer::Base.add_delivery_method :foo
ActionMailer::Base.add_delivery_method :bar
Run Code Online (Sandbox Code Playgroud)
我以为我能够创建一个电子邮件拦截器来做这样的事情:
class DeliveryMethodChooser
def self.delivering_email(message)
if some_condition
# code to use mail delivery method foo
else
# code to use mail delivery method bar
end
end
end
Run Code Online (Sandbox Code Playgroud)
但问题是,我不确定如何实际设置更改给定邮件使用的邮件传递方法.有任何想法吗?甚至可以动态选择要使用的delivery_method吗?
我试图在AngularJS中制作拦截器.我对AngularJS很新,发现了一些Interceptor的例子,但是无法让它工作.
在这里,我有我的app.js文件,其中包含所有相关代码.我还有一个控制器调用REST api并返回JSONP.
首先,我声明模块然后配置它(定义Interceptor).它现在应该捕获所有请求并输出到控制台...
使用app.factory创建拦截器是错误的吗?
var app = angular.module(
'TVPremieresApp',
[
'app.services'
, 'app.controllers'
]
);
app.config(function ($httpProvider) {
$httpProvider.responseInterceptors.push('errorInterceptor');
});
app.service('MessageService', function () {
// angular strap alert directive supports multiple alerts.
// Usually this is a distraction to user.
//Let us limit the messages to one
this.messages = [];
this.setError = function(msg) {
this.setMessage(msg, 'error', 'Error:');
};
this.setSuccess = function(msg) {
this.setMessage(msg, 'success', 'Success:');
};
this.setInfo = function (msg) {
this.setMessage(msg, 'info', 'Info:');
};
this.setMessage = function(content, type, …Run Code Online (Sandbox Code Playgroud) 我正在努力了解休息拦截器注释如何添加稍后在过滤器中可见的不同值.鉴于下面的代码,我希望在过滤器中,权限值将包含foo和bar,但它们是空的.任何帮助将不胜感激.
注解
package edu.psu.swe.fortress.poc.interceptor;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.enterprise.util.Nonbinding;
import javax.ws.rs.NameBinding;
@NameBinding
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(value=RetentionPolicy.RUNTIME)
public @interface FortressProtected
{
@Nonbinding String[] permissions() default {};
}
Run Code Online (Sandbox Code Playgroud)
过滤
package edu.psu.swe.fortress.poc.interceptor;
import java.io.IOException;
import java.lang.annotation.Annotation;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.ext.Provider;
@Provider
@FortressProtected
public class FortressAuthorizer implements ContainerRequestFilter
{
@Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
System.out.println("In the interceptor");
Class<?> clazz = this.getClass();
FortressProtected annotation = clazz.getAnnotation(edu.psu.swe.fortress.poc.interceptor.FortressProtected.class);
System.out.println("Annotation? " + clazz.isAnnotation());
for (Annotation a : clazz.getAnnotations())
{ …Run Code Online (Sandbox Code Playgroud) 我创建了axios拦截器,负责在每个请求发送到我的rest API之前添加令牌.
import axios from 'axios';
import { store } from '../store/store';
export default function execute() {
axios.interceptors.request.use(function(config) {
const token = store.state.token;
if(token) {
config.headers.Authorization = `Bearer ${token}`;
console.log(config);
return config;
} else {
console.log('There is not token yet...');
return config;
}
}, function(err) {
return Promise.reject(err);
});
}
Run Code Online (Sandbox Code Playgroud)
正如您在第2行中所看到的,我正在导入vuex存储,这实际上是我的令牌存放的位置.在第8行中,我实际上将此标记添加到config对象中,然后在下一行中我正在安慰它.
它在我的main.js文件中执行,如下所示:
import interceptor from './helpers/httpInterceptor.js';
interceptor();
Run Code Online (Sandbox Code Playgroud)
令牌存在于我在控制台中看到的配置对象中(因为我安慰了config对象):
每当我按预期提出一些API请求时,它就会运行.如果存在令牌(登录后),它应该为每个请求添加令牌头.不幸的是它没有添加它,虽然它存在于配置对象上,这让我有点困惑.
它实际上并没有将令牌添加到实际请求,因为我可以在网络选项卡中看到:
这个屏幕截图当然是在登录后进行的,因此令牌已经在vuex存储中,并且在我执行注销功能(调用其余API)之后它安慰了config(拦截器的一部分).
结果我有来自我的其余API的400(错误请求)状态,因为我没有发送令牌.
编辑!!!
我在想什么可以添加到这个问题,以使其更好.我认为创建demo plunker是不可能的,所以我决定创建一个小的存储库演示,您可以下载并查看问题.我希望它有助于解决问题!
我们最近在这个问题中讨论了一个用于OAuth身份验证令牌刷新的axios'拦截器.
基本上,拦截器应该做的是拦截任何带有401状态代码的响应并尝试刷新令牌.考虑到这一点,接下来要做的是从拦截器返回一个Promise,这样任何通常会失败的请求都会在令牌刷新后没有任何反应的情况下运行.
主要的问题是,拦截器只检查401状态代码,这是不够的,因为它refreshToken还会401在失败时返回状态代码 - 我们有一个循环.
我想到了两种可能的情况:
/auth/refresh它不应该尝试刷新令牌;refreshToken调用逻辑时省略一个拦截器第一个选项对我来说看起来有点"不动态".第二种选择看起来很有希望,但我不确定它是否可能发生.
那么主要的问题是,我们如何区分/识别拦截器中的调用并为它们运行不同的逻辑而不对其进行"硬编码",或者是否有任何方法可以省略指定调用的拦截器?先感谢您.
拦截器的代码可能有助于理解这个问题:
Axios.interceptors.response.use(response => response, error => {
const status = error.response ? error.response.status : null
if (status === 401) {
// will loop if refreshToken returns 401
return refreshToken(store).then(_ => {
error.config.headers['Authorization'] = 'Bearer ' + store.state.auth.token;
error.config.baseURL = undefined;
return Axios.request(error.config);
})
// Would be nice to catch an error here, which would work, if …Run Code Online (Sandbox Code Playgroud) interceptor ×10
axios ×2
java ×2
javascript ×2
actionmailer ×1
android ×1
angularjs ×1
aop ×1
ejb-3.0 ×1
guice ×1
http ×1
jax-rs ×1
login ×1
methods ×1
oauth ×1
oauth-2.0 ×1
okhttp ×1
retrofit ×1
spring ×1
spring-boot ×1
spring-mvc ×1
struts2 ×1
vue.js ×1
vuejs2 ×1