ฉันสามารถเขียนโปรแกรมปิดฤดูใบไม้ผลิ Bootแอพลิเคชันโดยไม่ต้องยกเลิก VM ?
ในงานอื่น ๆ สิ่งที่ตรงกันข้ามกับ
new SpringApplication(Main.class).run(args);
ฉันสามารถเขียนโปรแกรมปิดฤดูใบไม้ผลิ Bootแอพลิเคชันโดยไม่ต้องยกเลิก VM ?
ในงานอื่น ๆ สิ่งที่ตรงกันข้ามกับ
new SpringApplication(Main.class).run(args);
คำตอบ:
ปิดโดยทั่วไปหมายถึงการปิดพื้นฐานSpringApplication
วิธีช่วยให้คุณทราบว่าเป็น จากนั้นคุณสามารถทำได้ด้วยตัวเองApplicationContext
SpringApplication#run(String...)
ApplicationContext
ConfigurableApplicationContext
close()
ตัวอย่างเช่น,
@SpringBootApplication
public class Example {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(Example.class, args);
// ...determine it's time to shut down...
ctx.close();
}
}
หรือคุณสามารถใช้static
SpringApplication.exit(ApplicationContext, ExitCodeGenerator...)
วิธีการช่วยเหลือเพื่อดำเนินการให้คุณได้ ตัวอย่างเช่น,
@SpringBootApplication
public class Example {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(Example.class, args);
// ...determine it's time to stop...
int exitCode = SpringApplication.exit(ctx, new ExitCodeGenerator() {
@Override
public int getExitCode() {
// no errors
return 0;
}
});
// or shortened to
// int exitCode = SpringApplication.exit(ctx, () -> 0);
System.exit(exitCode);
}
}
ExitCodeGenerator
ใช้งาน คุณสามารถกลับจากmain
วิธีการเพื่อออกอย่างสง่างาม (ออกจากรหัส 0)
ในแอปพลิเคชันสปริงบูตคุณสามารถใช้สิ่งนี้ได้
ShutdownManager.java
import org.springframework.context.ApplicationContext;
import org.springframework.boot.SpringApplication;
@Component
class ShutdownManager{
@Autowired
private ApplicationContext appContext;
public void initiateShutdown(int returnCode){
SpringApplication.exit(appContext, () -> returnCode);
}
}
ApplicationContext
สามารถฉีดถั่วอื่นได้โดยอัตโนมัติ
งานนี้พิมพ์เสร็จแล้ว
SpringApplication.run(MyApplication.class, args).close();
System.out.println("done");
ดังนั้นการเพิ่ม.close()
หลังจากrun()
คำอธิบาย:
public ConfigurableApplicationContext run(String... args)
เรียกใช้แอปพลิเคชัน Spring สร้างและรีเฟรช ApplicationContext ใหม่ พารามิเตอร์:
args
- อาร์กิวเมนต์ของแอปพลิเคชัน (โดยปกติจะส่งมาจาก Java main method)ผลตอบแทน: ApplicationContext ที่กำลังรัน
และ:
void close()
ปิดบริบทของแอปพลิเคชันนี้ปล่อยทรัพยากรทั้งหมดและล็อกที่การใช้งานอาจมีอยู่ ซึ่งรวมถึงการทำลายถั่วซิงเกิลตันที่เก็บไว้ทั้งหมด หมายเหตุ: ห้ามเรียกปิดบนบริบทหลัก บริบทหลักมีวงจรชีวิตของตนเองและเป็นอิสระวิธีนี้สามารถเรียกใช้ได้หลายครั้งโดยไม่มีผลข้างเคียง: การโทรปิดตามมาในบริบทที่ปิดไปแล้วจะถูกละเว้น
โดยพื้นฐานแล้วจะไม่ปิดบริบทหลักนั่นคือสาเหตุที่ VM ไม่ปิด
SpringApplication.exit(appContext, () -> returnCode)
.
SpringApplication.run(MyApplication.class, args)
ว่าไม่มีบริบทหลัก มีเพียงหนึ่งบริบทบริบทที่สร้างขึ้นและกลับมาโดยที่คุณแล้วทันทีrun
close
@ ไมเคิลพูดถูก สิ่งนี้จะใช้ไม่ได้กับโปรแกรมที่ต้องทำอะไรเลยหลังจากเริ่มต้นบริบท Spring ซึ่งเป็นโปรแกรมส่วนใหญ่
ในแอปพลิเคชันคุณสามารถSpringApplication
ใช้ได้ นี้มีความคงที่exit()
วิธีการที่จะใช้เวลาสองข้อโต้แย้งที่: ApplicationContext
และExitCodeGenerator
:
กล่าวคือคุณสามารถประกาศวิธีนี้:
@Autowired
public void shutDown(ExecutorServiceExitCodeGenerator exitCodeGenerator) {
SpringApplication.exit(applicationContext, exitCodeGenerator);
}
ในการทดสอบการบูรณาการคุณสามารถทำได้โดยการเพิ่ม@DirtiesContext
คำอธิบายประกอบในระดับชั้นเรียน:
@DirtiesContext(classMode=ClassMode.AFTER_CLASS)
- ApplicationContext ที่เกี่ยวข้องจะถูกทำเครื่องหมายว่าสกปรกหลังจากคลาสทดสอบ@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
- ApplicationContext ที่เกี่ยวข้องจะถูกทำเครื่องหมายว่าสกปรกหลังจากแต่ละวิธีการทดสอบในคลาสกล่าวคือ
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {Application.class},
webEnvironment= SpringBootTest.WebEnvironment.DEFINED_PORT, properties = {"server.port:0"})
@DirtiesContext(classMode= DirtiesContext.ClassMode.AFTER_CLASS)
public class ApplicationIT {
...
สิ่งนี้จะทำให้แน่ใจว่าแอปพลิเคชัน SpringBoot ปิดอย่างถูกต้องและทรัพยากรจะถูกปล่อยกลับสู่ระบบปฏิบัติการ
@Autowired
private ApplicationContext context;
@GetMapping("/shutdown-app")
public void shutdownApp() {
int exitCode = SpringApplication.exit(context, (ExitCodeGenerator) () -> 0);
System.exit(exitCode);
}