当前位置: 首页 > 知识库问答 >
问题:

ApplicationScope类在每次Jersey 2.0时创建新的实例

鲁鸿
2023-03-14

我刚刚开始学习oAuth2授权来保护我的API。这个过程相当复杂。我的API是使用泽西和Apache Oltu作为oAuth2授权开发的。现在,可以生成令牌,但是,每次我尝试生成新令牌时,服务器都会创建一个@Application ationScoped bean的新实例。这是我从互联网上获得的bean代码:

@ApplicationScoped
public class Database {

private Set<String> authCodes = new HashSet<>();
private Set<String> tokens = new HashSet<>();

public void addAuthCode(String authCode) {
    authCodes.add(authCode);
}

public boolean isValidAuthCode(String authCode) {
    return authCodes.contains(authCode);
}

public void addToken(String token) {
    tokens.add(token);
}

public boolean isValidToken(String token) {
    return tokens.contains(token);
}
}

这是授权代码:

@Path("/authz")
public class AuthzEndpoint {

@Inject
Database database;

@GET
public Response authorize(@Context HttpServletRequest request)
        throws URISyntaxException, OAuthSystemException {
    try {
        OAuthAuthzRequest oauthRequest = new OAuthAuthzRequest(request);
        OAuthIssuerImpl oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());

        //build response according to response_type
        String responseType = oauthRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE);

        OAuthASResponse.OAuthAuthorizationResponseBuilder builder =
                OAuthASResponse.authorizationResponse(request, HttpServletResponse.SC_FOUND);

        if (responseType.equals(ResponseType.CODE.toString())) {
            final String authorizationCode = oauthIssuerImpl.authorizationCode();
            database.addAuthCode(authorizationCode);
            builder.setCode(authorizationCode);
        }
        if (responseType.equals(ResponseType.TOKEN.toString())) {
            final String accessToken = oauthIssuerImpl.accessToken();
            database.addToken(accessToken);

            builder.setAccessToken(accessToken);
            builder.setExpiresIn(3600l);
        }

        String redirectURI = oauthRequest.getParam(OAuth.OAUTH_REDIRECT_URI);
        final OAuthResponse response = builder.location(redirectURI).buildQueryMessage();
        URI url = new URI(response.getLocationUri());
        return Response.status(response.getResponseStatus()).location(url).build();
    } catch (OAuthProblemException e) {
        final Response.ResponseBuilder responseBuilder = Response.status(HttpServletResponse.SC_FOUND);
        String redirectUri = e.getRedirectUri();

        if (OAuthUtils.isEmpty(redirectUri)) {
            throw new WebApplicationException(
                    responseBuilder.entity("OAuth callback url needs to be provided by client!!!").build());
        }
        final OAuthResponse response =
                OAuthASResponse.errorResponse(HttpServletResponse.SC_FOUND)
                        .error(e).location(redirectUri).buildQueryMessage();
        final URI location = new URI(response.getLocationUri());
        return responseBuilder.location(location).build();
    }
}
}

如您所见,这里有数据库的@Inject注释,在代码的某些部分中调用了addToken()方法。当我尝试从我的主web服务验证令牌时,Databasebean是空的。这是密码

@Inject
Database database;

@POST
@Path("validateLogin")
@Consumes("application/x-www-form-urlencoded")
@Produces({"application/xml", "application/json", "text/plain", "text/html"})
public Response validateLogin(@HeaderParam("Authorization") String token, @FormParam("username") String username, @FormParam("password") String password) {

    System.out.println(token.substring(7,token.length()));
    System.out.println(database.isValidToken(token.substring(7, token.length())));
    System.out.println(database);

    if (!database.isValidToken(token.substring(7, token.length()))) {
        return Response.status(Response.Status.UNAUTHORIZED).build();
    }
    else {
        String result;
        if (username == null || password == null) {
            return Response.status(Response.Status.BAD_REQUEST).build();
        }
        else {
            STCWebService stcWebService = new STCWebService();
            result = stcWebService.validateLogin(username,password);
            if (result.isEmpty()) {
                return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
            }
            else {
                return Response
                        .status(200)
                        .entity(result)
                        .type(MediaType.APPLICATION_JSON)
                        .header("Access-Control-Allow-Origin", "*")
                        .header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
                        .build();
            }
        }
    }
}

我一直在想可能有一些错误在web.xml文件或ResourceConfig.java,甚至在Application Binder.我已经绊倒这个问题几个小时.任何帮助是感激。

编辑

这是应用程序管理器代码

public class MyApplicationBinder extends AbstractBinder {
    @Override
    protected void configure() {
        bind(Database.class).to(Database.class);
    }
}

并链接到此MyApplication

public class MyApplication extends ResourceConfig {
    public MyApplication() {
        register(new MyApplicationBinder());
        packages("com.package");
    }
}

我基于Jersey 2.0的依赖注入这个问题创建了ApplicationBinder和MyApplication代码

共有1个答案

闾丘玺
2023-03-14

问题是如何绑定数据库

bind(Database.class).to(Database.class); 

Application ationScoped将不起作用。您需要使用AbstractBinder配置范围。有几种方法。

> < li>

只是实例化它

bind(new Database()).to(Database.class);

这将自动使它成为单例。但是这样做的一个问题是,如果< code>Database有自己的依赖项,它们将不会被注入。为此,您可以使用下一个解决方案

使用(Scope)中的方法向服务添加范围。未提供时,默认范围是PerLookup,这意味着每次请求时都会创建一个新范围。还有其他范围,如SingletonRequest estScope

bind(Database.class).to(Database.class).in(Singleton.class);

确保它是javax.inject.Singleton而不是EJB。

你应该在链接到的问题中向下滚动到我的帖子:-)

 类似资料:
  • 我有以下ThreadPoolTaskExecator2配置 在我的公共类AdminService中,我有两个方法。 void triggerJob() 布尔执行sql(字符串sql) 如何将ThreadPoolTaskExecutor插入triggerJob方法,以便在第一个方法中调用executeSql时创建新线程。 在triggerjob中,我有一个基于条件调用executeSql的循环。 我

  • 问题内容: 我希望能够通过在已实例化的对象上调用方法来创建对象的新实例。例如,我有一个对象: 我希望能够调用并拥有两个有机体类型的对象。此时我的方法如下所示: 并且我非常确定它不起作用(我甚至不确定如何测试它。我在本文中尝试了gc方法)。那么,如何使我的对象创建自己的副本,就像我创建的第一个对象(带有)一样,该副本是可访问的? 问题答案: 另一个选项-如果方法中未使用实例(): 这样可以确保生物产

  • 我在android中使用BottomNavigationView来制作一个像Instagram一样的应用程序。我在NavigationTabs中使用片段。应用程序有5个标签初始我已经设置为活动标签的中间标签和加载它一旦应用程序启动。当我单击任何其他选项卡时,就会进行网络调用并加载数据。现在,当我按下on back按钮或再次单击last选项卡(在启动时加载)时,片段将被重新创建,并进行网络调用以加载

  • 我正在尝试在数据库上注册一个项目(6小时或12小时)后的特定时间发送通知。当我只注册一个项目时,通知工作良好,但是,如果我在一段时间内注册了两个项目,第一个通知将被第二个覆盖。 我知道我必须将id添加到挂起的意图中,可能还需要将id添加到实际通知中,但是我对alarmManager类不是很熟悉,也不知道应该在哪里添加id。如何使这两个通知相互独立? NotificationHelper类: 我开始

  • 这是我的箱子。我有三种不同类型的屏幕: 主菜单 有一个开始按钮切换到游戏屏幕。还允许玩家更改基本游戏设置。 实际可玩的游戏(玩家角色在其中奔跑和跳跃) 播放动画的屏幕,然后显示一个菜单,允许玩家再次启动游戏(即切换到GameScreen)或返回主菜单(即切换到MainMenuScreen) 我最好将屏幕存储在变量中,并在切换屏幕时重用它们,还是在处理完每个屏幕后将其丢弃,然后创建我要切换到的屏幕类

  • 我试了一下提供的指南,就像上面说的那样。 我经历了以下几个环节(以及SOW中的解决方案): https://github.com/erikjhordan-rey/dagger2-mvp-sample/issues/1 https://github.com/google/dagger/issues/942 什么都不起作用。 而且 而且