স্প্রিং বুট - চলমান বন্দরটি কীভাবে পাবেন


91

আমার একটি স্প্রিং বুট অ্যাপ্লিকেশন রয়েছে (এমবেডড টমক্যাট 7 ব্যবহার করে), এবং আমি server.port = 0আমার সেট করেছি application.propertiesযাতে আমার এলোমেলো বন্দর থাকতে পারে। সার্ভারটি বুট করার পরে এবং কোনও বন্দরে চলার পরে, আমাকে যে পোর্টটি বেছে নেওয়া হয়েছিল তা পেতে সক্ষম হতে হবে।

আমি @Value("$server.port")এটি ব্যবহার করতে পারছি না কারণ এটি শূন্য। এটি আপাতদৃষ্টিতে সরল তথ্যগুলির একটি টুকরো, তাই আমি কেন আমার জাভা কোড থেকে এটিকে অ্যাক্সেস করতে পারি না? আমি কীভাবে এটি অ্যাক্সেস করতে পারি?



ডক্সগুলিতে আরেকটি সম্ভাবনা পাওয়া যাবে: ডকস.স্প্রিং.আইও / স্প্রিং- বুট / ডকস / বর্তমান / রেফারেন্স / html/… ( time৪.৫ দেখুন রানটাইমের সময় এইচটিটিপি বন্দরটি আবিষ্কার করুন)
ডার্ক লাচোভস্কি

উত্তর:


97

একইভাবে পরিচালনা পোর্ট অ্যাক্সেস করাও কি সম্ভব, যেমন:

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

    @LocalServerPort
    int randomServerPort;

    @LocalManagementPort
    int randomManagementPort;

8
@LocalServerPortএর জন্য কেবল একটি শর্টকাট @Value("${local.server.port}")
deamon

4
@ ডিমন এর অর্থ আপনি যদি স্থানীয়.সেভার.পোর্টকে সম্পত্তিগুলিতে নির্দিষ্ট না করেন - এটি কাজ করে না
একা দাঁড়িয়ে

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();
      }
    }

আফাইক আপনি সার্ভার পোর্টের সাথে শিমটি কনফিগার করতে চাইলে এটি কাজ করবে না। সমস্ত মটরশুটি লোড হওয়ার পরে এবং সার্লেটগুলি নিবন্ধভুক্ত না হওয়া পর্যন্ত এই ইভেন্টটি বন্ধ করা হবে না।
মেরি

আমি কেন এটি মেনে নিলাম তা এটি আমার পক্ষে কাজ করেছিল। যদিও আমি হেনারের উত্তরটি চেষ্টা করে দেখিনি।
টাকার

দস্তাবেজগুলি পড়ার পরে আমি আপনার মতো কার্যত একই ছোট বর্গ নিয়ে এসেছি, নামকরণ করেছি PortProviderএবং একটি getPort()পদ্ধতি সরবরাহ করছি। PortProviderবন্দরের প্রয়োজনীয় নিয়ন্ত্রকের কাছে আমার স্বীকৃত এবং যখন আমার ব্যবসায়িক যুক্তি ডেকেছে portProvider.getPort(), রানটাইম পোর্টটি ফিরে আসবে।
ম্যাথু ওয়াইজ

12
স্প্রিং বুট ২.০ বা তারপরে যে কারও জন্য এটি চেষ্টা করছে, এপিআই কিছুটা পরিবর্তিত হয়েছে বলে মনে হচ্ছে। আমি আর সাবস্ক্রাইব করতে পারিনি EmbeddedServletContainerInitializedEvent, তবে একই ধরণের ক্লাস ServletWebServerInitializedEventরয়েছে যার একটি .getWebServer()পদ্ধতি রয়েছে। এটি আপনাকে পোর্ট টমক্যাট কমপক্ষে শুনছে get
নাইটলাইট

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আমার Spock ইন্টিগ্রেশন চশমা মধ্যে টীকা:

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

তারপরে এবং তারপরেই স্প্রিং অবশেষে একটি এলোমেলো বন্দরে টমক্যাট স্পিন করা শুরু করেছিল। আইএমএইচও এটি একটি স্প্রিং টেস্টিং ফ্রেমওয়ার্ক বাগ, তবে আমি নিশ্চিত যে এ সম্পর্কে তাদের নিজস্ব মতামত থাকবে।

আশা করি এটি কারও সাহায্য করেছে।


এই ঠিক একই সেটআপ আছে এবং এটি মধ্যে দৌড়ে। আমি ধরে নিলাম এটি কোনও অর্থে সমস্যাটি ছিল তবে আপনার সমাধানটি এখানে পোস্ট করার জন্য ধন্যবাদ। আপনি কি জানেন যে কেউ এটিকে এখনও বাগ হিসাবে লগ ইন করেছে?
bvulaj

16

টেস্টের সময় একটি এম্বেডড টমক্যাট উদাহরণ দ্বারা স্থানীয়.সার্ভার.পোর্ট মানটি ইনজেকশনের মাধ্যমে ব্যবহার করা পোর্টটি আপনি পেতে পারেন:

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

17
local.server.portকেবল তখনই সেট করা থাকে@WebIntegrationTests
17


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         
    }
}

এই উদাহরণটি স্প্রিং বুট অটো কনফিগারেশন এবং জ্যাক্স-আরএস (স্প্রিং এমভিসি নয়) ব্যবহার করে।


4
আমি swagger এর জন্য একই জিনিস চেয়েছিলাম
জিফ

1

স্প্রিং বুট 2 এর পরে, অনেক কিছু পরিবর্তন হয়েছে। দেওয়া উপরোক্ত উত্তর বসন্ত বুট 2. পূর্বে কাজ এখন যদি আপনি সার্ভারে পোর্টের জন্য রানটাইম আর্গুমেন্ট সহ আপনার আবেদন দৌড়াচ্ছে, তাহলে আপনি শুধুমাত্র সঙ্গে স্ট্যাটিক মান পাবেন @Value("${server.port}")যে উল্লেখ করা হয়, application.properties ফাইল। এখন প্রকৃত পোর্টটি পেতে যেখানে সার্ভারটি চলছে, নিম্নলিখিত পদ্ধতিটি ব্যবহার করুন:

    @Autowired
    private ServletWebServerApplicationContext server;

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

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

এছাড়াও, আপনি যদি লোড ভারসাম্যযুক্ত ইউরেকা / ডিসকভারি ক্লায়েন্ট হিসাবে আপনার অ্যাপ্লিকেশনগুলি ব্যবহার করছেন RestTemplateবা WebClient, উপরের পদ্ধতিটি সঠিক পোর্ট নম্বর প্রদান করবে।


4
এটি স্প্রিং বুট ২-এর সঠিক উত্তর @
কেন প্রোনোভিসি

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"));
    }

4
আমি আমার উত্তরে পরিবর্তন করেছি আপনি এখনও একই সমস্যা আছে?
আহমেদ

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;
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.