Saya memiliki aplikasi boot musim semi (menggunakan tomcat 7 tertanam), dan saya telah mengatur server.port = 0
di saya application.properties
sehingga saya dapat memiliki port acak. Setelah server di-boot dan berjalan di port, saya harus bisa mendapatkan port yang dipilih.
Saya tidak bisa menggunakan @Value("$server.port")
karena nol. Ini adalah informasi yang tampaknya sederhana, jadi mengapa saya tidak dapat mengaksesnya dari kode java saya? Bagaimana cara mengaksesnya?
spring
spring-boot
port
embedded-tomcat-7
Makanan
sumber
sumber
Jawaban:
Apakah mungkin juga untuk mengakses port manajemen dengan cara yang serupa, misalnya:
@SpringBootTest(classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT) public class MyTest { @LocalServerPort int randomServerPort; @LocalManagementPort int randomManagementPort;
sumber
@LocalServerPort
hanyalah jalan pintas untuk@Value("${local.server.port}")
.Lingkungan Spring menyimpan informasi ini untuk Anda.
@Autowired Environment environment; String port = environment.getProperty("local.server.port");
Di permukaan, ini terlihat identik dengan memasukkan bidang yang dianotasi
@Value("${local.server.port}")
(atau@LocalServerPort
, yang identik), di mana kegagalan pemasangan kabel otomatis dilemparkan saat permulaan karena nilainya tidak tersedia hingga konteksnya sepenuhnya diinisialisasi. Perbedaannya di sini adalah bahwa panggilan ini secara implisit dibuat dalam logika bisnis waktu proses daripada dipanggil saat aplikasi dimulai, dan karenanya 'pengambilan lambat' port diselesaikan dengan baik.sumber
environment.getProperty("server.port")
lakukan.Terima kasih kepada @Dirk Lachowski karena telah mengarahkan saya ke arah yang benar. Solusinya tidak seelegan yang saya inginkan, tetapi saya berhasil. Membaca dokumen musim semi, saya dapat mendengarkan di EmbeddedServletContainerInitializedEvent dan mendapatkan port setelah server aktif dan berjalan. Ini tampilannya -
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(); } }
sumber
PortProvider
, dan memberikangetPort()
metode. Autowired sayaPortProvider
ke pengontrol yang membutuhkan port, dan ketika logika bisnis saya dipanggilportProvider.getPort()
, port runtime dikembalikan.EmbeddedServletContainerInitializedEvent
, tetapi ada kelas serupa yang disebutServletWebServerInitializedEvent
yang memiliki.getWebServer()
metode. Ini akan memberi Anda port yang didengarkan Tomcat.Begitu juga orang lain yang telah mengonfigurasi aplikasi mereka seperti milik saya mendapat manfaat dari apa yang saya alami ...
Tak satu pun dari solusi di atas berhasil untuk saya karena saya memiliki
./config
direktori tepat di bawah basis proyek saya dengan 2 file:application.properties
application-dev.properties
Di
application.properties
saya punya:spring.profiles.active = dev # set my default profile to 'dev'
Di
application-dev.properties
saya punya:server_host = localhost server_port = 8080
Ini jadi ketika saya menjalankan tabung lemak saya dari CLI
*.properties
file akan dibaca dari./config
dir dan semuanya baik-baik saja.Nah, ternyata file properti ini sepenuhnya menggantikan
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
pengaturan di@SpringBootTest
spesifikasi Spock saya. Tidak peduli apa yang saya coba, bahkan denganwebEnvironment
set keRANDOM_PORT
Spring akan selalu memulai wadah Tomcat yang disematkan pada port 8080 (atau nilai apa pun yang saya tetapkan di./config/*.properties
file saya ).SATU - SATUNYA cara saya dapat mengatasi ini adalah dengan menambahkan eksplisit
properties = "server_port=0"
ke@SpringBootTest
anotasi dalam spesifikasi integrasi Spock saya:@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "server_port=0")
Kemudian, dan baru kemudian Spring akhirnya mulai memutar Tomcat di port acak. IMHO ini adalah bug kerangka pengujian Musim Semi, tapi saya yakin mereka akan memiliki pendapat sendiri tentang ini.
Semoga ini membantu seseorang.
sumber
Anda bisa mendapatkan port yang digunakan oleh instance Tomcat yang disematkan selama pengujian dengan memasukkan nilai local.server.port seperti:
// Inject which port we were assigned @Value("${local.server.port}") int port;
sumber
local.server.port
hanya disetel saat dijalankan dengan@WebIntegrationTests
Dimulai dengan Spring Boot 1.4.0 Anda dapat menggunakan ini dalam pengujian Anda:
import org.springframework.boot.context.embedded.LocalServerPort; @SpringBootTest(classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT) public class MyTest { @LocalServerPort int randomPort; // ... }
sumber
Tak satu pun dari solusi ini berhasil untuk saya. Saya perlu mengetahui port server saat membuat kacang konfigurasi Swagger. Menggunakan ServerProperties berhasil untuk saya:
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 } }
Contoh ini menggunakan konfigurasi otomatis Spring Boot dan JAX-RS (bukan Spring MVC).
sumber
Setelah Spring Boot 2, banyak hal yang berubah. Jawaban yang diberikan di atas berfungsi sebelum Spring Boot 2. Sekarang jika Anda menjalankan aplikasi dengan argumen runtime untuk port server, maka Anda hanya akan mendapatkan nilai statis dengan
@Value("${server.port}")
, yang disebutkan dalam file application.properties . Sekarang untuk mendapatkan port aktual tempat server berjalan, gunakan metode berikut:@Autowired private ServletWebServerApplicationContext server; @GetMapping("/server-port") public String serverPort() { return "" + server.getWebServer().getPort(); }
Juga, jika Anda menggunakan aplikasi Anda sebagai Klien Eureka / Discovery dengan beban seimbang
RestTemplate
atauWebClient
, metode di atas akan mengembalikan nomor port yang tepat.sumber
Anda bisa mendapatkan port server dari
@Autowired private HttpServletRequest request; @GetMapping(value = "/port") public Object getServerPort() { System.out.println("I am from " + request.getServerPort()); return "I am from " + request.getServerPort(); }
sumber
Harap pastikan Anda telah mengimpor paket yang benar
import org.springframework.core.env.Environment;
dan kemudian gunakan objek Lingkungan
@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")); }
sumber
Saya menyelesaikannya dengan semacam kacang proxy. Klien diinisialisasi saat dibutuhkan, pada saat itu port harus tersedia:
@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; } }
sumber