บทความและโครงการรหัสประกอบผ่านวิธีการที่จะเอาชนะอุปสรรคที่ย้ายไปยังแอปพลิเคชัน Spring 5 และ Spring Boot 2 ในคอนเทนเนอร์แอปพลิเคชัน WebSphere 8.5 (เป็น) ปัญหาที่เกิดขึ้นเมื่อฤดูใบไม้ผลิใช้ขวดตรวจสอบความถูกต้องที่อัปเดตและโดยค่าเริ่มต้นใช้กลยุทธ์การโหลดคลาสเฟิร์สคลาสที่จะยืนหยัดในการอัพเกรด
โดยเฉพาะตัวเลือกหลายตัวจะนำเสนอเกี่ยวกับวิธีการเปลี่ยนคลาสโหลดเดอร์เพื่อใช้พาเรนต์สุดท้าย นอกจากนี้เราเรียกขวดเฉพาะที่จำเป็นสำหรับการบูตฤดูใบไม้ผลิและสปริงในโครงการ JSP ตัวอย่างใน Maven Pom.xml ของคุณ
คาดว่าด้วยการเปลี่ยนแปลงเหล่านี้คุณสามารถโยกย้ายไปยังสปริงรุ่นที่รองรับได้ในขณะที่ยังคงการลงทุนของคุณอยู่ที่ 8.5 นั่นคือจนกว่าผลิตภัณฑ์เหล่านั้นจะถึงจุดจบของชีวิต
โดยค่าเริ่มต้น WebSphere Application Server 8.5.x (Was8) ใช้กลยุทธ์ตัวโหลดคลาส Parent_first โดยทั่วไปหมายความว่าจะโหลดขวดแอปพลิเคชันเซิร์ฟเวอร์ (EE) รุ่นก่อนและจัดลำดับความสำคัญของตัวเองในสิ่งที่อยู่ในการแจกจ่ายของคุณ
ตัวอย่างเช่นคุณอาจมี API การตรวจสอบความถูกต้องหนึ่งเวอร์ชันในไดเรกทอรี web-inf lib ของคุณ แต่เส้นทางคลาสจะเป็นที่โปรดปรานเป็นครั้งแรก การห้ามใช้เงาของคุณอย่างมีประสิทธิภาพในเวอร์ชั่น JEE ที่มาพร้อมกับ สิ่งนี้สมเหตุสมผลแล้ว IBM ใช้เวลาจำนวนมากในการรับรองและทดสอบเซิร์ฟเวอร์แอปพลิเคชันของพวกเขาด้วยชุด Javax ที่รู้จัก* ขวดและต้องการให้มันเป็นไปตามค่าเริ่มต้น
RUB เกิดขึ้นเมื่อคุณต้องการใช้ Spring 5.x และ Spring Boot 2.x รุ่นใหม่และเวอร์ชันเหล่านั้นใช้และพึ่งพา Javax Valtidation รุ่นใหม่และการตรวจสอบความถูกต้องของ Hibernate สำหรับฟังก์ชั่นหลักของพวกเขา คุณทำงานอะไร?
ตัวเลือกที่ 1 คือการอัพเกรดแอปพลิเคชันเซิร์ฟเวอร์ของคุณ สิ่งนี้ค่อนข้างตรงไปตรงมากับ Apache Tomcat, Open Liberty, JBoss และการใช้งานโอเพนซอร์สอื่น ๆ อีกมากมาย นี่เป็นเพราะความท้าทายที่ยิ่งใหญ่คือ แอปพลิเคชั่นที่สำคัญและดั้งเดิมจำนวนมากทำงานอยู่ที่ 8.5 กับ JDK 8.x เป็นเวลาหลายปีและธุรกิจมีความปรารถนาน้อยที่จะจ่ายสำหรับการทดสอบการถดถอยที่มีราคาแพง แน่นอนฤดูใบไม้ผลิ 4.x เป็นจุดจบของชีวิต แต่ก็ยังใช้งานได้ดังนั้นทำไมต้องอัพเกรด? คำตอบที่ดีที่สุดคือไม่ว่า 5.x นั้นเย็นกว่าและช่วยให้ฉันกลับมาทำงานได้ คำตอบที่แท้จริงคือช่องโหว่ คุณไม่ได้รับการสนับสนุนอีกต่อไปและนั่นคือปัญหาเมื่อไม่พบช่องโหว่ใหม่ในป่า คุณต้องการก้าวไปข้างหน้าของสถานการณ์นั้น
อะไรคืออะไร 9? ฉันทิ้งมันไว้กับคุณ โดยส่วนตัวถ้าคุณอพยพออกไปจากคือ 8 เว้นแต่คุณจะมีความต้องการที่จะตายสำหรับการกำหนดเองคือ 8 ฟังก์ชั่นการใช้งานโอเพนซอร์สด้านบนจะทำได้ดี คุณสามารถปรับใช้ให้มากที่สุดเท่าที่คุณต้องการในสถานที่มากมายเท่าที่คุณต้องการในทุกสภาพแวดล้อมคลาวด์ คอนเทนเนอร์หรือ on-prem ทางเลือกของคุณและ CFO ของคุณจะไม่สนใจ
ตัวเลือกที่เราจะไปที่นี่คือการสลับ classloader จากพาเรนต์ก่อนเป็นพาเรนต์สุดท้าย นี่ไม่ใช่วิธีแก้ปัญหาระยะยาว สิ่งนี้ทำให้คุณได้รับการสนับสนุนจากฤดูใบไม้ผลิและธุรกิจของคุณสามารถ "ฤดูใบไม้ผลิ" สำหรับการเปลี่ยนแปลงนั้น คุณได้รับมัน "ฤดูใบไม้ผลิ" ฉันเป็นคนพิการ นี่ไม่ใช่กระสุนเงิน ฉันแน่ใจว่าทีมโครงสร้างพื้นฐานของคุณลงทุนในสคริปต์ของพวกเขาและมีโหนดที่ทำงานได้ดีในกลุ่มที่มีเสถียรภาพ การปรับใช้โหนดใหม่กับ Parent Last อาจส่งผลกระทบต่อแอปพลิเคชันอื่น ๆ ที่ไม่ได้โยกย้าย แต่อยู่ในเซลล์เดียวกัน คุณทำอะไรที่นั่น?
มีหลายวิธีในการทำภารกิจนี้ให้สำเร็จ เราจะไม่เจาะลึกลงไปในข้อมูลเฉพาะเหล่านั้น ฉันจะให้โซลูชั่นระดับสูงสาม (3) ครั้งและให้คุณเลือก
นี่คือเอกสารที่เสี่ยงที่สุดและน้อยที่สุด ที่นี่คุณอัปเดตไฟล์ XML ที่คลุมเครือในหูของคุณด้วยคำอธิบายประกอบเฉพาะของ IBM และหวังว่าจะดีที่สุด ข้อดีคือคุณไม่จำเป็นต้องเปลี่ยนสคริปต์ของคุณ ข้อเสีย? ฉันไม่สามารถพิสูจน์ได้ว่างานนี้ในสภาพแวดล้อมการผลิต ด้านล่างนี้เป็นบทความสแต็กล้นในหัวข้อ ผู้ซื้อระวัง
อันนี้ใช้งานได้ดีและใช้งานได้ดีกับเวอร์ชันนักพัฒนาซอฟต์แวร์หรือถ้าคุณสามารถเข้าถึงคอนโซลผู้ดูแลระบบได้ ตัวเลือกนี้เป็นวิธีที่ยอดเยี่ยมในการพิสูจน์การเปลี่ยนแปลงของคุณ ปัญหาที่สำคัญของหลักสูตรคือการเปลี่ยนแปลงเหล่านี้ไม่สามารถปรับขนาดได้หรือไม่สามารถเขียนสคริปต์ได้ คุณอาจชอบตัวเลือกนี้ แต่ทีมโครงสร้างพื้นฐานของคุณไม่น่าจะอัปเดตหูของคุณอย่างมีความสุขหลังจากการปรับใช้ทุกโมดูล นี่ไม่ใช่ตัวเลือก Scable
นี่เป็นตัวเลือกเดียวของคุณสำหรับการผลิต คุณจะต้องทำงานร่วมกับทีมโครงสร้างพื้นฐานของคุณเพื่ออัปเดตสคริปต์การปรับใช้เพื่อเปลี่ยน classloader ระหว่างการปรับใช้และก่อนเริ่มแอปพลิเคชัน ฉันได้รวมไฟล์ Jython (PY) ของนักพัฒนาตัวอย่าง (ซึ่งหมายความว่าไม่ผ่านการทดสอบสูง)
คุณสามารถเห็นแรงบันดาลใจของฉันสำหรับสคริปต์ Jython จากที่นี่
print ( "Get Deployments : " )
deployments = AdminConfig . getid ( '/Deployment:' + APP_NAME + '/' )
print deployments
print ( "" )
print ( "Deployment Object" )
deploymentObject = AdminConfig . showAttribute ( deployments , 'deployedObject' )
print deploymentObject
myModules = AdminConfig . showAttribute ( deploymentObject , 'modules' )
myModules = myModules [ 1 : len ( myModules ) - 1 ]. split ( " " )
print myModules
for module in myModules :
if ( module . find ( 'WebModuleDeployment' ) != - 1 ):
AdminConfig . modify ( module , [[ 'classloaderMode' , 'PARENT_LAST' ]])
AdminConfig . save ()
print ( "Set module to PARENT_LAST" )การเปลี่ยนแปลงนี้เป็นเรื่องของคุณโดยสิ้นเชิง คุณจะต้องมีเซิร์ฟเวอร์นักพัฒนาซอฟต์แวร์หรือเซิร์ฟเวอร์ท้องถิ่นเพื่อดูและตรวจสอบการเปลี่ยนแปลงของคุณ แต่คุณต้องอัปเดต pom.xml ของคุณด้วยการเปลี่ยนแปลงเฉพาะสำหรับการตรวจสอบและไฮเบอร์เนต
หลังจากที่คุณปรับใช้ครั้งแรกและหลังจากเปลี่ยนคลาสโหลดเดอร์คุณจะเห็นข้อผิดพลาดด้านล่างในบันทึกระบบ:
เกิดจาก: java.lang.classnotfoundexception: javax.validation.parameternameprovider
ฤดูใบไม้ผลิ 5.x อาศัยเวอร์ชัน 2.x ของ ความถูกต้อง API ดังนั้นคุณจะต้องอัพเกรด API ใน POM ของคุณอย่างชัดเจน อีกครั้งสิ่งนี้เป็นไปได้เพียงเพราะคุณเปลี่ยนคลาสโหลดเดอร์ หากไม่มีการเปลี่ยนแปลงนั้นคุณจะติดโหลดเวอร์ชัน 1.x จากเส้นทางคลาสคือ ไม่มีการทำงานรอบ มีการเปลี่ยนแปลงอื่น ๆ หากคุณใช้หน้า JSP ดู POM.XML ในโครงการ WAS8-WAR
หมายเหตุพิเศษ หากคุณใช้กระเบื้อง 2.x คุณจะต้องอัพเกรดเป็นกระเบื้อง 3.x นั่นจะเป็นโพสต์อื่น
< dependency >
< groupId >javax.validation</ groupId >
< artifactId >validation-api</ artifactId >
< version >2.0.1.Final</ version >
</ dependency >ในขณะที่ไม่เฉพาะเจาะจงเราจำเป็นต้องรวมการพึ่งพา Tomcat-embed-Jasper เพื่อให้แอปพลิเคชันของเรารวบรวมและแสดงหน้า JSP สำหรับการทำงานในท้องถิ่น ไม่ใช่ ขอบเขต ที่กำหนดไว้สำหรับ การจัดเตรียมไว้
< dependency >
< groupId >org.apache.tomcat.embed</ groupId >
< artifactId >tomcat-embed-jasper</ artifactId >
< version >${tomcat-embed-jasper.version}</ version >
< scope >provided</ scope >
</ dependency >ดู Spring Boot 2.x readme.md สำหรับขวดเพิ่มเติมที่ต้องการ
คุณกำลังใช้ Java Config ถ้าคุณไปไกลขนาดนี้ ลืมการกำหนดค่า XML สไตล์เก่า นั่นคือฤดูใบไม้ผลิ 4.x คุณดีกว่าตอนนี้
โปรดทราบตำแหน่งสำหรับหน้า jsp: /web-inf/views/
@ Configuration
@ EnableWebMvc
@ ComponentScan ( basePackages = { "org.scavino" })
public class AppConfig {
/**
* ViewResolver allows setting properties such as
* prefix (/WEB-INF/views/) or suffix (*.jsp) to the view name to generate
* the final view page URL. In our case this is how
* we will configure JSP pages.
*
* @return JSP resolver with prefix set to /WEB-INF/views/
*/
@ Bean
public InternalResourceViewResolver resolver () {
InternalResourceViewResolver resolver = new InternalResourceViewResolver ();
resolver . setPrefix ( "/WEB-INF/views/" );
resolver . setSuffix ( ".jsp" );
return resolver ;
}
}เรากำลังขยาย AbstractannotationConfigDispatcherservletInitializer เพื่อให้สามารถเข้าถึงการกำหนดค่าคีย์ได้ ทำไม เราสามารถใช้คลาสความสะดวกสบายที่จัดทำโดยฤดูใบไม้ผลิแทนที่จะกำหนดค่า DispatchERServlet และ/หรือ ContextLoadERListener ด้วยตนเองด้วยตนเอง
public class SpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@ Override
protected Class <?> [] getRootConfigClasses () {
return null ;
}
@ Override
protected Class <?> [] getServletConfigClasses () {
return new Class [] {
AppConfig . class
};
}
@ Override
protected String [] getServletMappings () {
return new String [] {
"/"
};
}