स्प्रिंग बूट - रनिंग पोर्ट कैसे प्राप्त करें


91

मेरे पास एक स्प्रिंग बूट एप्लिकेशन है (एम्बेडेड टॉमकैट 7 का उपयोग करके), और मैंने अपने सेट server.port = 0में रखा है application.propertiesताकि मेरे पास एक यादृच्छिक पोर्ट हो सके। सर्वर बूट होने और पोर्ट पर चलने के बाद, मुझे उस पोर्ट को प्राप्त करने में सक्षम होना चाहिए जो चुना गया था।

मैं उपयोग नहीं कर सकता @Value("$server.port")क्योंकि यह शून्य है। यह जानकारी का एक साधारण सा टुकड़ा है, इसलिए मैं इसे अपने जावा कोड से एक्सेस क्यों नहीं कर सकता? मैं इसे कैसे एक्सेस कर सकता हूं?



डॉक्स में एक और संभावना पाई जा सकती है: docs.spring.io/spring-boot/docs/current/reference/html/… (64.5 रनटाइम में HTTP पोर्ट की खोज करें)
डिर्क लाचोव्सिया

जवाबों:


97

क्या प्रबंधन पोर्ट को एक समान तरीके से एक्सेस करना भी संभव है, जैसे:

  @SpringBootTest(classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT)
  public class MyTest {

    @LocalServerPort
    int randomServerPort;

    @LocalManagementPort
    int randomManagementPort;

8
@LocalServerPortबस के लिए एक शॉर्टकट है @Value("${local.server.port}")
बधिर

1
@deamon का मतलब है अगर आप लोकल को निर्दिष्ट नहीं करते हैं। संपत्तियों में एसपर्ट.पोर्ट - यह काम नहीं करेगा
अकेले

82

स्प्रिंग का पर्यावरण आपके लिए यह जानकारी रखता है।

@Autowired
Environment environment;

String port = environment.getProperty("local.server.port");

सतह पर यह एक एनोटेट @Value("${local.server.port}")(या @LocalServerPort, जो समान है) क्षेत्र को इंजेक्ट करने के लिए समान दिखता है , जिसके तहत स्टार्टअप पर एक असफलता को स्टार्टअप पर फेंक दिया जाता है क्योंकि संदर्भ पूरी तरह से प्रारंभ होने तक मूल्य उपलब्ध नहीं है। यहाँ अंतर यह है कि यह कॉल अप्रत्यक्ष रूप से रनटाइम बिज़नेस लॉजिक में किया जा रहा है, न कि एप्लिकेशन स्टार्टअप पर, और इसलिए पोर्ट का 'आलसी-भ्रूण' हल होता है।


4
किसी कारण से यह मेरे लिए काम नहीं environment.getProperty("server.port")किया , किया।
आनंद रॉकजॉव

25

मुझे सही दिशा में इंगित करने के लिए @ डार्च लाचोव्स्की को धन्यवाद। समाधान उतना सुरुचिपूर्ण नहीं है जितना मुझे पसंद होगा, लेकिन मैंने इसे काम कर लिया। स्प्रिंग डॉक्स को पढ़ते हुए, मैं एंबेडेड सर्वाइलेटकॉनटेनर इंसुलेटेड ईवेंट पर सुन सकता हूं और सर्वर के उठने और चलने के बाद पोर्ट प्राप्त कर सकता हूं। यहाँ यह कैसा दिखता है -

import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;




    @Component
    public class MyListener implements ApplicationListener<EmbeddedServletContainerInitializedEvent> {

      @Override
      public void onApplicationEvent(final EmbeddedServletContainerInitializedEvent event) {
          int thePort = event.getEmbeddedServletContainer().getPort();
      }
    }

AFAIK यह काम नहीं करेगा यदि आप सर्वर पोर्ट के साथ बीन को कॉन्फ़िगर करना चाहते हैं। इस घटना को तब तक नहीं हटाया गया जब तक कि सभी सेम लोड नहीं हो गए और सर्वलेट पंजीकृत हो गए।
MRE

यह मेरे लिए उस समय काम आया, जब मैंने इसे स्वीकार किया। मैंने हालांकि हेनर के जवाब की कोशिश नहीं की है।
टकर

डॉक्स पढ़ने के बाद, मैं लगभग उसी छोटे वर्ग के साथ आया था, जिसे आपने नाम दिया था PortProvider, और एक getPort()विधि प्रदान की । PortProviderपोर्ट की आवश्यकता वाले नियंत्रक के लिए मेरे द्वारा स्वतः लोड किया गया, और जब मेरे व्यावसायिक तर्क ने कॉल किया portProvider.getPort(), तो रनटाइम पोर्ट वापस आ गया।
मैथ्यू वार 12

12
स्प्रिंग बूट 2.0 या उसके बाद के किसी भी व्यक्ति के लिए, एपीआई थोड़ा बदल गया है। मैं अब सदस्यता नहीं ले पा रहा था EmbeddedServletContainerInitializedEvent, लेकिन एक समान वर्ग है जिसे ServletWebServerInitializedEventएक .getWebServer()विधि कहा जाता है । यह आपको तब मिलेगा जब टॉमकैट कम से कम सुन रहा हो।
नाइटलाइट

17

बस इतने ही लोग जिन्होंने अपने ऐप को कॉन्फ़िगर किया है जैसे मेरा फायदा है कि मुझे क्या फायदा हुआ ...

मेरे लिए काम किया क्योंकि मैं एक है ऊपर से कोई भी समाधान ./config: सिर्फ 2 फाइलों के साथ अपने प्रोजेक्ट आधार के तहत निर्देशिका

application.properties
application-dev.properties

में application.propertiesमेरे पास है:

spring.profiles.active = dev  # set my default profile to 'dev'

में application-dev.propertiesमेरे पास है:

server_host = localhost
server_port = 8080

ऐसा तब होता है जब मैं सीएलआई से अपना मोटा जार चलाता हूं, *.propertiesफाइलों को ./configडायर से पढ़ा जाएगा और सब अच्छा है।

खैर, यह पता चला है कि ये गुण फाइलें मेरे स्पॉक स्पेक्स में webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORTसेटिंग को पूरी तरह से ओवरराइड करती हैं @SpringBootTest। कोई फर्क नहीं पड़ता कि मैंने क्या कोशिश की, यहां तक ​​कि स्प्रिंग के webEnvironmentसेट RANDOM_PORTपर भी पोर्ट 8080 पर एम्बेडेड टॉमकैट कंटेनर (या जो भी मूल्य मैं अपनी ./config/*.propertiesफाइलों में सेट करता हूं ) को स्टार्टअप करूंगा ।

केवल जिस तरह से मैं दूर करने के लिए यह एक स्पष्ट जोड़कर था सक्षम था properties = "server_port=0"करने के लिए @SpringBootTestमेरी स्पॉक एकीकरण चश्मा में एनोटेशन:

@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "server_port=0")

फिर, और उसके बाद ही स्प्रिंग ने आखिरकार टॉमकैट को एक यादृच्छिक बंदरगाह पर स्पिन करना शुरू कर दिया। IMHO यह स्प्रिंग टेस्टिंग फ्रेमवर्क बग है, लेकिन मुझे यकीन है कि इस पर उनकी अपनी राय होगी।

आशा है कि यह किसी की मदद की।


यह एक ही सेटअप है और यह भी भाग गया। मैंने मान लिया कि यह कुछ अर्थों में मुद्दा था, लेकिन आपके समाधान को यहाँ पोस्ट करने के लिए धन्यवाद। क्या आप जानते हैं कि किसी ने इसे बग के रूप में अभी तक लॉग इन किया है?
bvulaj

16

आप परीक्षण के दौरान एक एम्बेडेड टोमैट उदाहरण द्वारा उपयोग किया जा रहा पोर्ट प्राप्त कर सकते हैं।

// Inject which port we were assigned
@Value("${local.server.port}")
int port;

17
local.server.portकेवल तभी सेट होता है जब साथ में चल रहा हो@WebIntegrationTests
ejain


12

स्प्रिंग बूट 1.4.0 से शुरू करके आप इसे अपने परीक्षण में उपयोग कर सकते हैं:

import org.springframework.boot.context.embedded.LocalServerPort;

@SpringBootTest(classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT)
public class MyTest {

  @LocalServerPort
  int randomPort;

  // ...
}

8

इनमें से किसी भी समाधान ने मेरे लिए काम नहीं किया। स्वैगर कॉन्फ़िगरेशन बीन का निर्माण करते समय मुझे सर्वर पोर्ट को जानना आवश्यक था। ServerProperties का उपयोग मेरे लिए काम किया:

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.ws.rs.ApplicationPath;

import io.swagger.jaxrs.config.BeanConfig;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;

import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.stereotype.Component;

@Component
@ApplicationPath("api")
public class JerseyConfig extends ResourceConfig 
{
    @Inject
    private org.springframework.boot.autoconfigure.web.ServerProperties serverProperties;

    public JerseyConfig() 
    {
        property(org.glassfish.jersey.server.ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
    }

    @PostConstruct
    protected void postConstruct()
    {
        // register application endpoints
        registerAndConfigureSwaggerUi();
    }

    private void registerAndConfigureSwaggerUi()
    {
        register(ApiListingResource.class);
        register(SwaggerSerializers.class);

        final BeanConfig config = new BeanConfig();
        // set other properties
        config.setHost("localhost:" + serverProperties.getPort()); // gets server.port from application.properties file         
    }
}

यह उदाहरण स्प्रिंग बूट ऑटो कॉन्फ़िगरेशन और JAX-RS (स्प्रिंग MVC नहीं) का उपयोग करता है।


1
मैं स्वैगर के लिए एक ही चीज चाहता था
Jeef

1

स्प्रिंग बूट 2 के बाद, बहुत कुछ बदल गया है। ऊपर दिए गए उत्तर स्प्रिंग बूट 2 से पहले काम करते हैं। अब यदि आप सर्वर पोर्ट के लिए रनटाइम आर्ग्युमेंट्स के साथ अपना एप्लिकेशन चला रहे हैं, तो आपको केवल स्टैटिक वैल्यू ही मिलेगी @Value("${server.port}"), जो कि एप्लीकेशन.प्रॉपीटीज़ फ़ाइल में उल्लिखित है । अब वास्तविक पोर्ट प्राप्त करने के लिए जिसमें सर्वर चल रहा है, निम्न विधि का उपयोग करें:

    @Autowired
    private ServletWebServerApplicationContext server;

    @GetMapping("/server-port")
    public String serverPort() {

        return "" + server.getWebServer().getPort();
    }

इसके अलावा, यदि आप अपने अनुप्रयोगों का उपयोग यूरेका / डिस्कवरी ग्राहकों के रूप में लोड संतुलित के साथ कर रहे हैं RestTemplateया WebClient, उपरोक्त विधि सटीक पोर्ट नंबर को वापस कर देगी।


1
स्प्रिंग बूट के लिए यह सही उत्तर है। @SpringBootTest और WebEnvironment.RandOM_PORT के साथ ठीक काम करता है।
केन प्रोनोविसी

1

आप सर्वर पोर्ट से प्राप्त कर सकते हैं

HttpServletRequest
@Autowired
private HttpServletRequest request;

@GetMapping(value = "/port")
public Object getServerPort() {
   System.out.println("I am from " + request.getServerPort());
   return "I am from  " + request.getServerPort();
}
    

0

कृपया सुनिश्चित करें कि आपने सही पैकेज आयात किया है

import org.springframework.core.env.Environment;

और फिर पर्यावरण वस्तु का उपयोग करें

@Autowired
private Environment env;    // Environment Object containts the port number

 @GetMapping("/status")
  public String status()
    {
   return "it is runing on"+(env.getProperty("local.server.port"));
    }

1
मैंने अपने उत्तर में बदलाव किए हैं क्या आप अभी भी वही समस्या हैं?
अहमद

0

मैंने इसे एक तरह के प्रॉक्सी बीन से हल किया। क्लाइंट की जरूरत होने पर उसे इनिशियलाइज़ किया जाता है, तब तक पोर्ट उपलब्ध होना चाहिए:

@Component
public class GraphQLClient {

    private ApolloClient apolloClient;
    private final Environment environment;

    public GraphQLClient(Environment environment) {
        this.environment = environment;
    }

    public ApolloClient getApolloClient() {
        if (apolloClient == null) {
            String port = environment.getProperty("local.server.port");
            initApolloClient(port);
        }
        return apolloClient;
    }

    public synchronized void initApolloClient(String port) {
        this.apolloClient = ApolloClient.builder()
                .serverUrl("http://localhost:" + port + "/graphql")
                .build();
    }

    public <D extends Operation.Data, T, V extends Operation.Variables> GraphQLCallback<T> graphql(Operation<D, T, V> operation) {
        GraphQLCallback<T> graphQLCallback = new GraphQLCallback<>();
        if (operation instanceof Query) {
            Query<D, T, V> query = (Query<D, T, V>) operation;
            getApolloClient()
                    .query(query)
                    .enqueue(graphQLCallback);
        } else {
            Mutation<D, T, V> mutation = (Mutation<D, T, V>) operation;
            getApolloClient()
                    .mutate(mutation)
                    .enqueue(graphQLCallback);

        }
        return graphQLCallback;
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.