JavaRush /Java блогы /Random-KK /Hello World-тан Spring Web MVC-ге дейін және оған сервлет...
Viacheslav
Деңгей

Hello World-тан Spring Web MVC-ге дейін және оған сервлеттердің қандай қатысы бар

Топта жарияланған
Сәлем әлемінен Spring Web MVC-ге дейін және оған сервлеттердің қандай қатысы бар - 1

Кіріспе

Біз білетіндей, Java-ның жетістігі желіге қосылуға ұмтылатын бағдарламалық жасақтаманың эволюциясының арқасында келді. Сондықтан біз кәдімгі « Hello World » консольдік қосымшасын негізге аламыз және оның консольдік қолданбадан желілік қолданба болу үшін не қажет екенін түсінеміз. Сонымен, алдымен Java жобасын жасау керек. Бағдарламашылар - жалқау адамдар. Тарихқа дейінгі дәуірде, кейбіреулері мамонттарды аулап жүргенде, басқалары отырып, Java кітапханалары мен каталог құрылымдарының әртүрлілігінде шатастырмауға тырысты. Әзірлеуші ​​қосымшаны жасау процесін басқара алатындай етіп, ол жай ғана «Мен осындай және осындай 2-нұсқаның кітапханасын қалаймын» деп жаза алатындай етіп, олар арнайы құралдарды - жүйелерді құрастыруды ойлап тапты. Ең танымал екеуі - Мэвен және Градл . Бұл мақала үшін біз Gradle бағдарламасын қолданамыз. Егер бұрын каталог құрылымын өзіміз жасауымыз керек болса, енді Gradle Gradle Init плагинін пайдалана отырып, бір командада каталог құрылымы мен негізгі негізгі класы бар Java жобасын жасауға мүмкіндік береді: gradle init --type java-application Бұл пәрмен үшін инициализацияны (init) орындайды. бізге Hello World консолі бар Java қолданбасы (java-application). Аяқтағаннан кейін файл каталогта пайда болады - build.gradle . Бұл біздің құрастыру сценарийі - яғни бұл үшін қандай әрекеттерді орындау керектігі сипатталған қосымшаны құруға арналған белгілі бір сценарий. Оны ашып, оған жолды қосамыз: jar.baseName = 'webproject' Gradle жобада әртүрлі әрекеттерді орындауға мүмкіндік береді және бұл әрекеттер тапсырмалар деп аталады . Пәрменді (тапсырманы) орындау арқылы /build/libsgradle build каталогында JAR файлы жасалады . Ал, сіз ойлағандай, оның атауы енді webproject.jar болады . Бірақ орындасақ , қате пайда болады: . Себебі java қосымшасы үшін белгілі бір манифестті тіркеу керек – бұл қосымшамен жұмыс істеу, оны қабылдаудың сипаттамасы. Содан кейін java қосымшасын орындайтын JVM қай сынып бағдарламаға кіру нүктесі және басқа ақпарат (мысалы, сынып жолы) екенін біледі. Егер құрастыру сценарийінің мазмұнын мұқият қарастыратын болсақ, қосылатын плагиндерді көреміз. Мысалы: Егер біз Gradle Java Plugin бетіне өтсек , манифестті конфигурациялай алатынымызды көреміз: java -jar ./build/libs/webproject.jarno main manifest attributeapply plugin: 'java'
jar {
    manifest {
        attributes 'Main-Class': 'App'
    }
}
Негізгі класс, бағдарламаға кіру нүктесі біз үшін Gradle Init Plugin арқылы жасалған. Және ол тіпті mainClassName параметрінде көрсетілген. Бірақ бұл бізге ұнамады, өйткені... бұл параметр басқа плагинге, Gradle қолданбасының плагиніне сілтеме жасайды . Сонымен, бізде экранда Hello World көрсететін Java қолданбасы бар. Бұл Java қолданбасы JAR (Java ARchive) ішінде жинақталған. Бұл қарапайым, консольге негізделген, заманауи емес. Оны веб-қосымшаға қалай айналдыруға болады?
От Hello World до Spring Web MVC и при чём тут сервлеты - 2

Сервлет API

Java желімен жұмыс істей алуы үшін ерте заманда Servlet API деп аталатын спецификация пайда болды . Дәл осы спецификация клиент пен serverдің өзара әрекеттесуін, клиенттен хабарлама алуды (мысалы, браузер) және жауапты жіберуді (мысалы, бет мәтінімен) сипаттайды. Әрине, содан бері көп нәрсе өзгерді, бірақ мәселе Java қолданбасы веб-қосымшаға айналуы үшін Servlet API қолданылады. Негізсіз болжам жасамау үшін дәл осы спецификацияны алайық: JSR-000340 JavaTM Servlet 3.1 . Бізді ең алдымен « 1-тарау: шолу » қызықтырады . Ол біз түсінуге тиіс негізгі ұғымдарды сипаттайды. Біріншіден, сервлет дегеніміз не? « 1.1 Сервлет дегеніміз не? » тарауында Сервлет контейнер арқылы басқарылатын және динамикалық мазмұнды жасайтын Java құрамдас бөлігі екені айтылады . Басқа Java компоненттері сияқты, сервлет byte-codeқа құрастырылған және Java технологиясы арқылы веб-serverге жүктелетін Java класы болып табылады. Сервлеттердің веб-клиентпен (мысалы, браузер) Сервлет контейнері жүзеге асыратын сұрау/жауап парадигмасы шеңберінде әрекеттесуі маңызды. Сервлеттер қандай да бір сервлет контейнерінде тұрады екен. Бұл не? « 1.2 Сервлет контейнері дегеніміз не? » тарауында Сервлет контейнері сұраулар жіберілетін және жауаптар жіберілетін желілік қызметтерді ұсынатын веб-serverдің немесе қолданбалы serverдің кейбір бөлігі екені айтылады . Бұл Сервлет контейнері сервлеттердің өмірлік циклін басқарады. Барлық Сервлет Контейнерлер HTTP протоколын кем дегенде қолдауы керек, бірақ басқаларына қолдау көрсетуі мүмкін. Мысалы, HTTPS. Сервлет контейнері сервлеттер орындалатын ортаға қауіпсіздікке қатысты кез келген шектеулерді қоя алатыны да маңызды. Сондай-ақ, « 10.6 Веб қолданбасының мұрағат файлына » сәйкес веб-бағдарлама WAR (Web ARchive) файлында пакеттелген болуы маңызды. Яғни, енді біз басқа нәрсе үшін банканы және қолданба плагиндерін алып тастауымыз керек. Және бұл Gradle WAR плагині . Ал jar.baseName орнына war.baseName себебін көрсетіңіз Біз енді jar плагинін пайдаланbyteындықтан, манифест параметрлерін де алып тастадық. Біз JAR іске қосқан кезде, Java виртуалды машинасына (JVM) біздің қолданбамен қалай жұмыс істеу керектігін манифест арқылы айту керек болды. Өйткені JVM оны іске қосты. Веб-қосымшаны веб-serverдің қандай да бір түрі орындайтын сияқты. Оған біздің веб-қосымшамен қалай жұмыс істеу керектігін айту керек пе? Және бұл иә болып шықты. Веб-қосымшалардың өздерінің арнайы манифесі бар. Ол Deployment Descriptor деп аталады . Бүкіл бөлім оған арналған: “ 14. Орналастыру дескрипторы ”. Маңызды бөлім бар: « 10-тарау:". Ол Servlet API тұрғысынан веб-қосымшаның не екені туралы айтады. Мысалы, " 10.5 Каталог құрылымы " тарауында орналастыру дескрипторы қай жерде болуы керектігі көрсетілген: /WEB-INF/web.xml. WEB-INF қайда орналастыру керек? Gradle WAR плагинінде айтылғандай, ол жаңа макет қосады : src/main/webapp.Сондықтан осындай каталогты жасайық, ішінде біз WEB-INF каталогын жасаймыз, ал ішінде web.xml файлын жасаймыз.Каталогтың болуы маңызды. META-INF емес, WEB-INF деп аталады! Оны " 14.5.1 Негізгі мысал " XML мысалынан көшіріп алайық :
От Hello World до Spring Web MVC и при чём тут сервлеты - 3
Көріп отырғанымыздай, конфигурациялау үшін XML құжаты қолданылады. XML құжаты жарамды (Жарамды) деп есептелуі үшін кейбір «схемаға» сәйкес келуі керек. Мұны XML құжатының интерфейсінің бір түрі ретінде қарастыруға болады. Схема XML құжатында қандай элементтер болуы мүмкін екенін, қандай деректер түрі элементті, ретті, талапты және басқа аспектілерді анықтай алатынын көрсетеді. Құжаттамадан көшірілген мысал 2.5 нұсқасын көрсетеді, бірақ біз 3.1 нұсқасын пайдаланғымыз келеді. Әрине, нұсқалар өзгерген сайын спецификация өзгерді және жаңа мүмкіндіктер қосылды. Сондықтан, 2.5 нұсқасы (web-app_2_5.xsd) үшін пайдаланылғаннан басқа схеманы пайдалану керек. 3.1 нұсқасы үшін қандай схеманы пайдалануым керек? Құжаттама бізге осы мәселеде көмектеседі, « 14.3 Орналастыру дескрипторы » тарауы, яғни specification is available at http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd біз схемаға сілтемені барлық жерде көрсетілген xsd-мен ауыстыруымыз керек, оны version="2.5"3.1-ге өзгертуді ұмытпауымыз керек, сонымен қатар барлық жерде аттар кеңістігін өзгерту керек ( xmlns және xsi:schemaLocation ішінде). Олар қай аттар кеңістігінде жұмыс істейтінімізді көрсетеді (қарапайым тілмен айтқанда, қандай элемент атауларын пайдалана аламыз). Схема файлын ашсаңыз, targetNamespace біз көрсетуге тиісті аттар кеңістігін қамтиды:
От Hello World до Spring Web MVC и при чём тут сервлеты - 4
Естеріңізде болса, Jar файлының манифестінде біз қай классты пайдаланғымыз келетінін жазған болатынбыз. Мұнда не істеу керек? Мұнда біз веб-клиенттен сұрау алған кезде қандай сервлет сыныбын қолданғымыз келетінін көрсетуіміз керек. Сипаттаманы « 14.4 Орналастыру дескрипторының диаграммасы » тарауында оқуға болады . Ол келесідей болады:
От Hello World до Spring Web MVC и при чём тут сервлеты - 5
Мұнда бәрі қарапайым. Серверлет жарияланады, содан кейін ол белгілі бір үлгімен салыстырылады. Бұл жағдайда /app. Үлгі орындалғанда, сервлет әдісі орындалады. Сұлулық үшін қолданба сыныбы xml конфигурациясын түзетуді ұмытпай, пакетке көшірілуі керек. Бірақ бұл бәрі емес. Қолданба сервлет болуы керек. Сервлет болу нені білдіреді? Бұл HttpServlet -тен мұра алуымыз керек дегенді білдіреді . Мысалды " 8.1.1 @WebServlet " тарауынан көруге болады . Оған сәйкес біздің App класы келесідей болады:
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class App extends HttpServlet {
    public String getGreeting() {
        return "Hello world.";
    }

	public void doGet(HttpServletRequest request, HttpServletResponse response) {
		response.setContentType("text/html");
		try {
			response.getWriter().println(getGreeting());
		} catch (IOException e) {
			throw new IllegalStateException(e);
		}
	}
}
Бірақ біздің жоба әлі дайын емес. Өйткені біз қазір Servlet API 3.1 нұсқасына тәуелдіміз. Бұл біздің құрастыру сценарийінде Servlet API-ге тәуелділікті көрсетуіміз керек дегенді білдіреді. JVM codeта жазғаныңыздың дұрыс екенін және оны қалай пайдалану керектігін білуі керек. Естеріңізде болса, спецификация негізінен барлығының қалай жұмыс істейтінін сипаттайтын интерфейстер ғана. Ал іске асыру веб-server жағында жатыр. Сондықтан, Servlet API болмаса, Maven Central жүйесінде қажетті кітапхананы табу болады: javax.servlet-api . Тәуелділіктер блогына жазба қосыңыз . Maven репозиторийінде, сіз көргендей, ол қамтамасыз етілген дейді. Тәуелділікті пайдаланбас бұрын, аумақты көрсету керек. Gradle-де "берілген" деп аталатын аумақ жоқ, бірақ оның " тек компиляция " ауқымы бар. Сондықтан біз мынаны көрсетеміз: providedCompile 'javax.servlet:javax.servlet-api:3.1.0' Уф, бәрі жақсы сияқты ма? Gradle Build жобамызды WAR файлына құрастырады. Ал енді онымен не істеуіміз керек? Біріншіден, бізге веб-server қажет. Google-де біз « веб-serverдің java тізімі » деп жазамыз және веб-serverлердің тізімін көреміз. Осы тізімнен таңдайық, мысалы, TomCat . Apache Tomcat веб-сайтына өтіңіз , соңғы нұсқасын (қазіргі 9 нұсқасы) zip мұрағаты ретінде жүктеп алыңыз (Windows үшін болса). Оны кейбір каталогқа шығарыңыз. Ура, бізде веб-server бар. bin ішкі каталогындағы веб-server каталогынан біз пәрмен жолынан catalina орындаймыз және қолжетімді опцияларды көреміз. жасайық: catalina start. Әрбір веб-serverде веб-server бақылайтын каталогы болады. Онда веб-бағдарлама файлы пайда болса, веб-server оны орнатуды бастайды. Бұл орнату орналастыру немесе орналастыру деп аталады . Иә иә, сондықтан « орналастыру дескрипторы ». Яғни, қолданбаны қалай дұрыс орналастыру керек. Tomcat-та бұл каталог webapps болып табылады . Онда gradle build көмегімен жасаған соғысты көшіріп алайық. Осыдан кейін журналда біз келесідей нәрсені көреміз: Жақсырақ түсіну үшін tomcat каталогында келесі жолдарды қоса отырып, Deployment of web application archive [tomcat\webapps\webproject.war] has finished in [время] ms файлды өңдейміз :\conf\tomcat-users.xml
От Hello World до Spring Web MVC и при чём тут сервлеты - 6
Енді serverді қайта іске қосамыз (catalina stop, catalina start) және addressке барамыз.Бұл http://127.0.0.1:8080/manager жерде біз барлық қолданбалардың жолдарын көреміз. Біздің веб-жобаға /webproject жолы берілген болуы мүмкін. Бұл қандай жол? " 10.1 Веб-serverлердегі веб-қосымшалар " тарауындағы спецификация веб-бағдарламаның қолданба ішіндегі кейбір жолмен байланысты екенін айтады (бұл жағдайда, /webproject). Осы жол арқылы барлық сұраулар бірдей ServletContext-пен байланыстырылады. Бұл жолды contextRoot деп те атайды . Және " 10.2 ServletContext қатынасына " сәйкес сервлет контейнері веб-бағдарлама мен ServletContext бір-біріне қатыстырады. Яғни, әрбір веб-қосымшаның өзінің ServletContext бар. ServletContext дегеніміз не ? Техникалық сипаттамада көрсетілгендей, ServletContext сервлеттерді олар іске қосылған " бағдарлама көрінісімен" қамтамасыз ететін нысан болып табылады . Servlet мәтінмәні Servlet API спецификациясының 4-тарауында толығырақ сипатталған. Бір қызығы, 3.1 нұсқасындағы Servlet API енді web.xml болуын талап етпейді. Мысалы, annotationлар арқылы сервлетті анықтауға болады:
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/app2")
public class App2 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html");
        response.getWriter().println("app2");
    }
}
Сондай-ақ келесі тақырып бойынша ұсынылады: " Java EE сұхбаты - JEE Servlet API (сұрақтар мен жауаптар) ". Сонымен, бізде Сервлет бар - ол веб-клиентке қандай жауап беруге жауапты. Бізде пайдаланушыдан сұрауларды қабылдайтын, сервлет жолымен қол жеткізілген жолға сәйкес келетін және сәйкестік табылса, Сервлетті орындайтын ServletContainer бар. Жақсы. Бұл әлем суретінде көктем қандай орын алады ?

Spring Web MVC

Керемет, бізде веб-қосымша бар. Енді көктемді қосу керек. Мұны қалай істей аламыз? Алдымен көктемді жобаға қалай дұрыс қосу керектігін анықтау керек. Бұрын көктемгі платформа жобасының құжаттамасына сәйкес мұны істеуге болатыны белгілі болды , бірақ қазір « Платформа 2019 жылдың 9 сәуірінде қолдау көрсетілетін қызмет мерзімін аяқтайды », яғни оны жасау ұсынылмайды. оны қолданыңыз, өйткені ол жақын арада бұдан былай қолдау көрсетпейді. Шығудың жалғыз жолы - « Платформа пайдаланушыларына Spring Boot тәуелділігін басқаруды пайдалануды бастау ұсынылады ». Сондықтан Spring Boot құжаттамасына көшейік . Түсіндіруге рұқсат етіңіздер, біз Spring Boot қолданбасының өзін емес, тек Spring Boot-тен тәуелділікті басқаруды қолданамыз. Яғни, Spring Boot жобасы кітапханалардың қай нұсқаларын (соның ішінде Spring MVC) пайдалану керектігі туралы білім бере алады. Онда біз 3.2 табамыз . Spring Boot тәуелділігін басқаруды оқшаулауда пайдалану . Құжаттамаға сәйкес құрастыру сценарийіне келесіні қосыңыз:
plugins {
    id 'org.springframework.boot' version '2.0.4.RELEASE' apply false
}
apply plugin: 'io.spring.dependency-management'
Және
dependencyManagement {
    imports {
        mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
    }
}
Көріп отырғаныңыздай, біз көрсеттік apply false, яғни. Біз Spring Boot қолданбасының өзін пайдаланбаймыз, бірақ тәуелділікті басқаруды сол жерден қолданамыз. Бұл тәуелділікті басқару BOM деп те аталады - " Материалдар тізімі ". Енді біз Spring Web MVC жобасының өзін қосуға дайынбыз. Spring Web MVC Spring Framework жобасының бөлігі болып табылады және бізді " Web Servlet " бөлімі қызықтырады . Құрылым сценарийіне тәуелділікті қосамыз: compile 'org.springframework:spring-webmvc'. Көріп отырғанымыздай, біз ауқымды компиляцияны орнаттық, өйткені веб-server бізге көктемді бермейді. Біздің жоба Көктем кітапханасын өз ішіне қосуға мәжбүр. Әрі қарай, біз үшін « 1.2. DispatcherServlet » бөлімін оқу маңызды , мұнда Spring MVC « Front controller » үлгісінің айналасында құрылған , мұнда конфигурацияны және басқа компоненттерге өкілдік беруді қамтамасыз ететін қандай да бір орталық сервлет бар. . Диспетчерді диспетчер деп аударуға болады. Сонымен, ең алдымен, web.xml файлында мынаны жариялаймыз:
От Hello World до Spring Web MVC и при чём тут сервлеты - 7
Көріп отырғанымыздай, бұл шын мәнінде Servlet API спецификациясында анықталған тұрақты тыңдаушы. Дәлірек айтсақ, бұл ServletContextListener, яғни ол біздің веб-бағдарлама үшін Сервлет мәтінмәнін инициализациялау үшін іске қосылған. Әрі қарай, Spring-ке параметрлері бар арнайы xml конфигурациясының қай жерде орналасқанын көрсететін параметрді көрсету керек:
От Hello World до Spring Web MVC и при чём тут сервлеты - 8
Көріп отырғаныңыздай, бұл жай ғана Сервлет мәтінмән деңгейінде сақталатын, бірақ қолданба мәтінмәнін инициализациялау кезінде Spring пайдаланатын кәдімгі параметр. Енді барлық сервлеттердің орнына барлық басқа сұрауларды тарататын бір диспетчерді жариялау керек.
От Hello World до Spring Web MVC и при чём тут сервлеты - 9
Ал мұнда ешқандай сиқыр жоқ. Қарасақ, бұл HttpServlet, мұнда Spring оны құрылымға айналдыратын көптеген нәрселерді жасайды. Арнайы URL үлгісін сервлетпен салыстыру (карталау) ғана қалады:
От Hello World до Spring Web MVC и при чём тут сервлеты - 10
Бәрі бұрынғыдай. Енді веб-serverіміз көрсетуі керек нәрсені жасайық. Мысалы, WEB-INF ішінде беттер ішкі каталогын жасайық, сонда hello.jsp файлы болады. Мазмұн ең қарапайым болуы мүмкін. Мысалы, html тегтерінің ішінде « Hello World » мәтіні бар h1 тегі бар . applicationContext.xmlБіз бұрын көрсеткен файлды жасауды ұмытпаңыз . Spring құжаттамасынан мысал келтірейік: " 1.10.3. Класстарды автоматты түрде анықтау және бұршақ анықтамаларын тіркеу ".
От Hello World до Spring Web MVC и при чём тут сервлеты - 11
Өйткені біз осылайша автоматты анықтауды қосамыз, енді біз 2 класс жасай аламыз (арнайы көктемгі annotationларды пайдалану себебінен олар Көктемгі бұршақ деп саналады), оны Spring енді өзі жасайды және олардың көмегімен біздің қосымшамызды теңшейді:
  1. Веб конфигурациясы, мысалы, Java мәнері конфигурациясы:

    @Configuration
    @EnableWebMvc
    public class WebConfig implements WebMvcConfigurer {
        @Override
        public void configureViewResolvers(ViewResolverRegistry registry) {
            registry.jsp("/WEB-INF/pages/", ".jsp");
        }
        @Override
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
        }
    }

    Бұл мысал Spring Framework құжаттамасында сипатталған: " 1.11. MVC конфигурациясы ".

    Мұнда біз jsp беттерінің қай жерде орналасқанын анықтауға көмектесетін ViewResolver бағдарламасын тіркейміз. Екінші әдіс « Әдепкі сервлеттің » қосылғанын қамтамасыз етеді.

    Бұл туралы толығырақ мына жерден оқи аласыз: « Әдепкі-сервлет-өңдеуші не қажет және оны пайдалану ».

  2. Нақты JSP-ге сұрауларды салыстыруды сипаттауға арналған HelloController контроллері

    @Controller
    public class HelloController {
        @GetMapping("/hello")
        public String handle(Model model) {
            return "hello";
        }
    }

    Мұнда біз құжаттамада " 1.4. Аннотацияланған контроллерлер " тарауында сипатталған @Controller annotationсын қолдандық.

Енді, қолданбамыз орналастырылған кезде, сұрау жіберген кезде /webproject/hello(мұнда /webproject мәтінмән түбірі болып табылады), алдымен DispatcherServlet өңделеді. Ол негізгі диспетчер ретінде біздің /* ағымдағы сұрауға сәйкес келетінін анықтайды, яғни DispatcherServlet бірдеңе істеуі керек. Содан кейін ол тапқан барлық салыстырулардан өтеді. Ол /hello-ға салыстырылған және оны орындайтын дескриптор әдісі бар HelloController бар екенін көреді. Бұл әдіс «сәлем» мәтінін қайтарады. Бұл мәтінді ViewResolver алады, ол serverге клиентке көрсетілуі керек jsp файлдарын қайдан іздеу керектігін айтады. Осылайша, клиент осы өте қымбат бетті алады.

Қорытынды

Мақалада «контекст» сөзінің қорқынышты емес екені анық болады деп үміттенемін. Бұл сипаттамалар өте пайдалы болып шықты. Ал құжаттама біздің жауымыз емес, досымыз. Көктемнің неге негізделгені, ол қалай қосылатыны және Servlet API оған не қатысы бар екені анық болады деп үміттенемін.
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION