JavaRush /Java Blog /Random-TL /Mula sa Hello World hanggang Spring Web MVC at kung ano a...

Mula sa Hello World hanggang Spring Web MVC at kung ano ang kinalaman ng mga servlet dito

Nai-publish sa grupo
Mula sa Hello World hanggang Spring Web MVC at ano ang kinalaman ng mga servlet dito - 1

Panimula

Tulad ng alam natin, tiyak na dumating ang tagumpay ng Java salamat sa ebolusyon ng software na nagsusumikap na kumonekta sa network. Samakatuwid, gagawin namin ang karaniwang console application na " Hello World " bilang batayan at mauunawaan kung ano ang kailangan nito upang maging isang network application mula sa isang console application. Kaya, kailangan mo munang lumikha ng isang proyekto ng Java. Ang mga programmer ay mga taong tamad. Noong sinaunang panahon, nang ang ilan ay nangangaso ng mga mammoth, ang iba ay nakaupo at sinubukang huwag malito sa buong iba't ibang mga aklatan ng Java at mga istruktura ng direktoryo. Upang makontrol ng developer ang proseso ng paglikha ng isang application, upang maisulat lamang niya ang "Gusto ko ng isang library ng ganito at ganoong bersyon 2," nakagawa sila ng mga espesyal na tool - bumuo ng mga system. Ang dalawang pinakasikat ay sina Maven at Gradle . Para sa artikulong ito gagamitin namin ang Gradle. Kung mas maaga ay kailangan naming gumawa ng istraktura ng direktoryo sa aming sarili, ngayon ang Gradle, gamit ang Gradle Init Plugin, ay nagpapahintulot sa amin na lumikha ng isang proyekto ng Java na may istraktura ng direktoryo at isang batayang Pangunahing klase sa isang utos: Ang gradle init --type java-application utos na ito ay nagsasagawa ng pagsisimula (init) para sa sa amin ng isang Java application (java-application ) na may console na Hello World. Pagkatapos makumpleto, lilitaw ang isang file sa direktoryo - build.gradle . Ito ang aming build script - iyon ay, isang partikular na script para sa paglikha ng isang application na may paglalarawan kung anong mga aksyon ang kailangang gawin para dito. Buksan natin ito at idagdag ang linya dito: jar.baseName = 'webproject' Pinapayagan ka ng Gradle na magsagawa ng iba't ibang mga aksyon sa isang proyekto at ang mga pagkilos na ito ay tinatawag na mga gawain . Sa pamamagitan ng pagpapatupad ng isang command (gawain) isang JAR file ay malilikha gradle buildsa /build/libs direktoryo . At, gaya ng nahulaan mo, magiging webproject.jar na ang pangalan nito . Ngunit kung ipapatupad natin ang java -jar ./build/libs/webproject.jar, magkakaroon tayo ng error: no main manifest attribute. Ito ay dahil para sa isang java application kailangan mong mag-attach ng isang manifest - ito ay isang paglalarawan kung paano magtrabaho kasama ang application, kung paano ito malalaman. Pagkatapos ay malalaman ng JVM, na magpapatupad ng java application, kung aling klase ang entry point sa programa at iba pang impormasyon (halimbawa, classpath). Kung susuriin nating mabuti ang mga nilalaman ng build script, makikita natin ang mga plugin na konektado. Halimbawa: apply plugin: 'java' Kung pupunta tayo sa Gradle Java Plugin page , makikita natin na maaari nating i-configure ang manifest:
jar {
    manifest {
        attributes 'Main-Class': 'App'
    }
}
Ang pangunahing klase, ang entry point sa programa, ay binuo para sa amin ng Gradle Init Plugin. At ito ay tinukoy pa sa mainClassName parameter. Ngunit hindi ito nababagay sa amin, dahil... ang setting na ito ay tumutukoy sa isa pang plugin, Gradle Application Plugin . Kaya, mayroon kaming Java application na nagpapakita ng Hello World sa screen. Ang Java application na ito ay nakabalot sa isang JAR (Java ARchive). Ito ay simple, console-based, hindi up-to-date. Paano ito gawing web application?
От Hello World до Spring Web MVC и при чём тут сервлеты - 2

Servlet API

Upang makapagtrabaho ang Java sa network, lumitaw ang isang detalye na tinatawag na Servlet API noong sinaunang panahon . Ang pagtutukoy na ito ay naglalarawan ng pakikipag-ugnayan ng client-server, pagtanggap ng mensahe mula sa isang kliyente (halimbawa, isang browser) at pagpapadala ng tugon (halimbawa, kasama ang teksto ng isang pahina). Naturally, marami ang nagbago mula noon, ngunit ang punto ay upang ang isang Java application ay maging isang web application, ang Servlet API ay ginagamit. Upang hindi mag-isip nang walang batayan, kunin natin ang mismong detalyeng iyon: JSR-000340 JavaTM Servlet 3.1 . Una sa lahat, interesado kami sa " Kabanata 1: Pangkalahatang-ideya ". Inilalarawan nito ang mga pangunahing konsepto na dapat nating maunawaan. Una, ano ang isang servlet? Ang kabanata na " 1.1 Ano ang isang Servlet? " ay nagsasabi na ang isang Servlet ay isang bahagi ng Java na pinamamahalaan ng isang lalagyan at na bumubuo ng dynamic na nilalaman. Tulad ng iba pang mga bahagi ng Java, ang isang servlet ay isang klase ng Java na pinagsama-sama sa bytecode at maaaring i-load sa isang web server gamit ang teknolohiya ng Java. Mahalagang makipag-ugnayan ang mga servlet sa isang web client (halimbawa, isang browser) sa loob ng balangkas ng paradigm ng kahilingan/tugon, na ipinapatupad ng Servlet Container. Lumalabas na ang mga Servlet ay nakatira sa ilang uri ng Servlet Container. Ano ito? Sa kabanata na " 1.2 Ano ang isang Servlet Container? " sinasabing ang isang Servlet Container ay ilang bahagi ng isang web server o application server na nagbibigay ng mga serbisyo sa network kung saan ipinapadala ang mga kahilingan at ipinapadala ang mga tugon. Ang mismong Servlet Container na ito ang namamahala sa life cycle ng mga servlet. Lahat ng Servlet Container ay kinakailangang suportahan ang HTTP protocol sa pinakamababa, ngunit maaaring suportahan ang iba. Halimbawa, HTTPS. Mahalaga rin na ang Servlet Container ay maaaring magpataw ng anumang mga paghihigpit na nauugnay sa seguridad sa kapaligiran kung saan ang mga servlet ay isinasagawa. Mahalaga rin na ayon sa " 10.6 Web Application Archive File " ang web application ay dapat na naka-package sa isang WAR (Web ARchive) file. Ibig sabihin, ngayon ay kailangan nating tanggalin ang ating garapon at mga plugin ng application para sa ibang bagay. At ito ang plugin ng Gradle WAR . At sa halip na jar.baseName tukuyin ang war.baseName Dahil Dahil hindi na namin ginagamit ang jar plugin, inalis na rin namin ang mga setting ng manifest. Noong inilunsad namin ang JAR, ang Java Virtual Machine (JVM) ay kailangang sabihin sa pamamagitan ng manifest kung paano gagana sa aming aplikasyon. Dahil ang JVM ang nagpapatakbo nito. Ang web application, tila, ay pinaandar ng ilang uri ng web server. Lumalabas na kailangan niyang sabihin sa kanya kung paano magtrabaho sa aming web application? At lumalabas na oo. Ang mga web application ay may sariling espesyal na manifesto. Ito ay tinatawag na Deployment Descriptor . Ang isang buong seksyon ay nakatuon dito: " 14. Deployment Descriptor ". Mayroong mahalagang seksyon: " Kabanata 10:". Pinag-uusapan nito kung ano ang isang web application mula sa punto ng view ng Servlet API. Halimbawa, sa kabanata " 10.5 Direktoryo Structure " ito ay ipinahiwatig kung saan ang Deployment Descriptor ay dapat na: /WEB-INF/web.xml. Saan ilalagay ang WEB-INF? Gaya ng nakasaad sa Gradle WAR plugin , nagdaragdag ito ng bagong layout : src/main/webapp. Samakatuwid, gumawa tayo ng ganoong direktoryo, sa loob ay gagawa tayo ng direktoryo ng WEB-INF, at sa loob ay gagawa tayo ng web.xml file. Mahalaga na ang direktoryo ay tinatawag na WEB-INF, at hindi META-INF! Kopyahin natin ito mula sa " 14.5.1 A Basic Example " XML na halimbawa:
От Hello World до Spring Web MVC и при чём тут сервлеты - 3
Tulad ng nakikita natin, isang XML na dokumento ang ginagamit para sa pagsasaayos. Ang isang XML na dokumento, upang maituring na wasto (Valid), ay dapat sumunod sa ilang "schema". Maaari mong isipin ito bilang isang uri ng interface para sa isang XML na dokumento. Tinutukoy ng schema kung anong mga elemento ang maaaring nasa isang XML na dokumento, kung anong uri ng data ang maaaring tukuyin ang elemento, pagkakasunud-sunod, kinakailangan, at iba pang aspeto. Ang halimbawang kinopya mula sa dokumentasyon ay nagpapahiwatig ng bersyon 2.5, ngunit gusto naming gamitin ang bersyon 3.1. Naturally, nagbago ang detalye habang nagbago ang mga bersyon, at nagdagdag ng mga bagong feature. Samakatuwid, kailangan mong gumamit ng schema maliban sa ginamit para sa bersyon 2.5 (web-app_2_5.xsd). Anong scheme ang dapat kong gamitin para sa bersyon 3.1? Ang dokumentasyon ay makakatulong sa amin dito, kabanata " 14.3 Deployment Descriptor ", na nagsasaad specification is available at http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd Iyon ay, kailangan naming palitan ang link sa schema ng tinukoy na xsd sa lahat ng dako, hindi nakakalimutang baguhin ito version="2.5"sa 3.1, at baguhin din ang namespace sa lahat ng dako ( xmlns at sa xsi:schemaLocation). Isinasaad nila sa loob kung saang namespace tayo gagana (upang ilagay ito nang napakasimple, anong mga pangalan ng elemento ang maaari nating gamitin). Kung bubuksan mo ang schema file, ang targetNamespace ay maglalaman ng parehong namespace na dapat naming tukuyin:
От Hello World до Spring Web MVC и при чём тут сервлеты - 4
Tulad ng naaalala namin, sa Manifest of the Jar file isinulat namin kung aling klase ang gusto naming gamitin. Anong gagawin dito? Dito kailangan nating tukuyin kung aling klase ng servlet ang gusto nating gamitin kapag nakatanggap tayo ng kahilingan mula sa isang web client. Ang paglalarawan ay mababasa sa kabanata " 14.4 Deployment Descriptor Diagram ". Magiging ganito ang hitsura:
От Hello World до Spring Web MVC и при чём тут сервлеты - 5
Simple lang ang lahat dito. Ang serverlet ay idineklara, at pagkatapos ito ay nakamapa sa isang tiyak na template. Sa kasong ito, sa /app. Kapag ang template ay naisakatuparan, ang servlet method ay isasagawa. Para sa kagandahan, ang klase ng App ay dapat ilipat sa package, hindi nakakalimutang itama ang xml configuration. Ngunit hindi lang iyon. Ang app ay dapat na isang servlet. Ano ang ibig sabihin ng pagiging isang servlet? Nangangahulugan ito na dapat tayong magmana mula sa HttpServlet . Ang isang halimbawa ay makikita sa kabanata " 8.1.1 @WebServlet ". Ayon dito, magiging ganito ang hitsura ng aming klase ng 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);
		}
	}
}
Ngunit ang aming proyekto ay hindi pa handa. Dahil umaasa na kami ngayon sa Servlet API version 3.1. Nangangahulugan ito na sa aming build script kailangan naming magpahiwatig ng dependency sa Servlet API. Kailangang malaman ng JVM na tama ang isinulat mo sa code at kung paano ito gamitin. Tulad ng naaalala namin, ang detalye ay mahalagang mga interface lamang na naglalarawan kung paano dapat gumana ang lahat. At ang mga pagpapatupad ay nasa panig ng web server. Samakatuwid, kung wala ang Servlet API magkakaroon ng Find the required library sa Maven Central: javax.servlet-api . At magdagdag ng entry sa dependencies block . Sa repositoryo ng Maven, tulad ng nakita mo, sinasabi nito na ibinigay. Bago gumamit ng dependency, dapat mong tukuyin ang saklaw. Ang Gradle ay walang saklaw na pinangalanang "provided", ngunit mayroon itong " compile only " scope. Samakatuwid, ipahiwatig namin: providedCompile 'javax.servlet:javax.servlet-api:3.1.0' Ugh, parang ayos lang ang lahat? Gagawin ng Gradle Build ang aming proyekto sa isang WAR file. At ano ang susunod nating gagawin dito? Una, kailangan namin ng isang Web Server. Sa Google nagsusulat kami ng " java list ng web server " at nakakakita ng listahan ng mga web server. Pumili tayo sa listahang ito, halimbawa, TomCat . Pumunta sa website ng Apache Tomcat , i-download ang pinakabagong bersyon (kasalukuyang bersyon 9) bilang isang zip archive (kung para sa Windows). I-unpack ito sa ilang direktoryo. Hurray, mayroon kaming web server. Mula sa direktoryo ng web server sa subdirectory ng bin , isinasagawa namin ang catalina mula sa command line at nakikita ang mga magagamit na opsyon. Ating gawin: catalina start. Ang bawat web server ay may direktoryo na sinusubaybayan ng web server. Kung ang isang web application file ay lilitaw doon, ang web server ay magsisimulang i-install ito. Ang pag-install na ito ay tinatawag na deployment o deployment . Oo oo, kaya naman " descriptor ng deployment ". Iyon ay, kung paano maayos na i-deploy ang application. Sa Tomcat ang direktoryo na ito ay webapps . Gayahin natin ang digmaan na ginawa natin gamit ang gradle build doon. Pagkatapos nito, sa log ay makikita natin ang isang bagay tulad ng: Deployment of web application archive [tomcat\webapps\webproject.war] has finished in [время] ms Upang mas maunawaan pa, sa direktoryo ng tomcat ay ie-edit namin ang file \conf\tomcat-users.xml, pagdaragdag ng mga sumusunod na linya:
От Hello World до Spring Web MVC и при чём тут сервлеты - 6
Ngayon ay i-restart namin ang server (catalina stop, catalina start) at pumunta sa address. http://127.0.0.1:8080/manager Dito makikita natin ang mga path ng lahat ng application. Ang aming webproject ay malamang na binigyan ng path /webproject. Ano ang landas na ito? Ang detalye sa kabanata na " 10.1 Web Applications Within Web Servers " ay nagsasaad na ang isang web application ay nauugnay sa ilang landas sa loob ng application (sa kasong ito, /webproject). Ang lahat ng mga kahilingan sa pamamagitan ng landas na ito ay mauugnay sa parehong ServletContext. Ang landas na ito ay tinatawag ding contextRoot . At ayon sa " 10.2 Relasyon sa ServletContext " iniuugnay ng servlet container ang web application at ang ServletContext nang isa-isa. Ibig sabihin, ang bawat web application ay may sariling ServletContext. Ano ang ServletContext ? Gaya ng isinasaad ng detalye, ang ServletContext ay isang bagay na nagbibigay sa mga servlet ng "view ng application " kung saan sila tumatakbo. Ang Konteksto ng Servlet ay inilalarawan nang mas detalyado sa Kabanata 4 ng detalye ng Servlet API. Nakakagulat, ang Servlet API sa bersyon 3.1 ay hindi na nangangailangan ng web.xml na naroroon. Halimbawa, maaari mong tukuyin ang isang servlet gamit ang mga anotasyon:
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");
    }
}
Inirerekomenda din sa paksa: " Panayam sa Java EE - JEE Servlet API (Mga Tanong at Sagot) ". Kaya, mayroon kaming Servlet - responsable ito sa kung anong tugon ang ibibigay sa web client. Mayroon kaming ServletContainer na tumatanggap ng mga kahilingan mula sa user, tumutugma sa path na na-access sa path sa servlet, at kung may nakitang tugma, ipapatupad ang Servlet. ayos lang. Anong lugar ang inookupahan ng Spring sa larawang ito ng mundo ?

Spring Web MVC

Mahusay, mayroon kaming isang web application. Ngayon kailangan nating ikonekta ang Spring. Paano natin ito magagawa? Una, kailangan mong malaman kung paano maayos na ikonekta ang Spring sa iyong proyekto. Lumalabas na mas maaga ay posible itong gawin alinsunod sa dokumentasyon ng proyekto ng Spring platform , ngunit ngayon " Ang Platform ay maaabot ang katapusan ng suportadong buhay nito sa Abril 9, 2019 ", iyon ay, hindi ipinapayong gamitin ito, dahil malapit na itong hindi na susuportahan. Ang tanging paraan ay " Hinihikayat ang mga gumagamit ng Platform na simulang gamitin ang pamamahala ng dependency ng Spring Boot ". Samakatuwid, lumipat tayo sa dokumentasyon ng Spring Boot . Hayaan akong linawin na hindi namin ginagamit ang Spring Boot mismo, ngunit ang Dependency Management lamang mula sa Spring Boot. Iyon ay, ang proyekto ng Spring Boot ay maaaring magbigay ng kaalaman tungkol sa kung aling mga bersyon ng mga aklatan ang gagamitin (kabilang ang Spring MVC). Doon ay makikita natin ang 3.2. Paggamit ng dependency management ng Spring Boot sa paghihiwalay . Ayon sa dokumentasyon, idagdag ang sumusunod sa build script:
plugins {
    id 'org.springframework.boot' version '2.0.4.RELEASE' apply false
}
apply plugin: 'io.spring.dependency-management'
At
dependencyManagement {
    imports {
        mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
    }
}
Tulad ng nakikita mo, ipinahiwatig namin apply false, i.e. Hindi namin ginagamit ang Spring Boot mismo, ngunit gumagamit kami ng pamamahala ng dependency mula doon. Ang pamamahala ng dependency na ito ay tinatawag ding BOM - " Bill Of Materials ". Ngayon ay handa na kaming ikonekta ang mismong proyekto ng Spring Web MVC. Ang Spring Web MVC ay bahagi ng proyekto ng Spring Framework at interesado kami sa seksyong " Web Servlet ". Idagdag natin ang dependency sa build script: compile 'org.springframework:spring-webmvc'. Tulad ng nakikita natin, itinakda namin ang scope compile, dahil ang web server ay hindi nagbibigay sa amin ng Spring. Ang aming proyekto ay pinilit na isama ang Spring library sa loob mismo. Susunod, mahalagang basahin natin ang seksyong " 1.2. DispatcherServlet ", kung saan sinasabi na ang Spring MVC ay binuo sa paligid ng pattern na " Front controller ", kung saan mayroong ilang uri ng central servlet na nagbibigay ng configuration at delegasyon sa iba pang mga bahagi . Maaaring isalin ang dispatcher bilang dispatcher. Kaya, una sa lahat, sa web.xml ipinapahayag namin:
От Hello World до Spring Web MVC и при чём тут сервлеты - 7
Gaya ng nakikita natin, isa talaga itong regular na Listener na tinukoy sa detalye ng Servlet API. Upang maging mas tumpak, ito ay isang ServletContextListener, ibig sabihin, ito ay na-trigger upang simulan ang Servlet Context para sa aming web application. Susunod, kailangan mong tukuyin ang isang setting na magsasabi sa Spring kung saan matatagpuan ang espesyal na xml config nito na may mga setting:
От Hello World до Spring Web MVC и при чём тут сервлеты - 8
Gaya ng nakikita mo, isa lang itong regular na setting na nakaimbak sa antas ng Servlet Context, ngunit gagamitin ng Spring kapag sinisimulan ang Application Context. Ngayon ay kailangan mong ideklara, sa halip na lahat ng mga servlet, isang solong dispatcher na namamahagi ng lahat ng iba pang mga kahilingan.
От Hello World до Spring Web MVC и при чём тут сервлеты - 9
At walang magic dito. Kung titingnan natin, ito ay isang HttpServlet, kung saan gumagawa ang Spring ng maraming bagay na ginagawa itong isang balangkas. Ang natitira na lang ay ang pag-uugnay (mapa) ng isang partikular na template ng URL sa servlet:
От Hello World до Spring Web MVC и при чём тут сервлеты - 10
Ang lahat ay katulad ng dati. Ngayon, gumawa tayo ng isang bagay na dapat ipakita ng ating web server. Halimbawa, gumawa tayo ng subdirectory ng mga pahina sa ating WEB-INF, at magkakaroon ng file na hello.jsp. Ang nilalaman ay maaaring ang pinaka-primitive. Halimbawa, sa loob ng mga html tag ay mayroong h1 tag na may text na " Hello World ". At huwag kalimutang likhain ang file applicationContext.xmlna tinukoy namin kanina. Kumuha tayo ng isang halimbawa mula sa dokumentasyon ng Spring: " 1.10.3. Awtomatikong pag-detect ng mga klase at pagrerehistro ng mga kahulugan ng bean ".
От Hello World до Spring Web MVC и при чём тут сервлеты - 11
kasi pinapagana namin ang autodetection sa ganitong paraan, maaari na kaming lumikha ng 2 klase (ituturing silang Spring Beans dahil sa paggamit ng mga espesyal na anotasyon ng Spring), na gagawin na ngayon ng Spring mismo at iko-customize ang aming application sa kanilang tulong:
  1. Configuration sa web halimbawa configuration ng istilo ng 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();
        }
    }

    Ang halimbawang ito ay inilarawan sa dokumentasyon ng Spring Framework: " 1.11. MVC Config ".

    Dito kami nagrerehistro ng ViewResolver, na makakatulong sa pagtukoy kung saan matatagpuan ang mga jsp page. Tinitiyak ng pangalawang paraan na ang " Default na servlet " ay pinagana.

    Maaari mong basahin ang higit pa tungkol dito: " Ano ang kailangan at paggamit ng default-servlet-handler ".

  2. HelloController controller para sa paglalarawan ng pagmamapa ng mga kahilingan sa isang partikular na JSP

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

    Dito ginamit namin ang @Controller annotation na inilarawan sa dokumentasyon sa kabanata " 1.4. Annotated Controllers ".

Ngayon, kapag na-deploy ang aming application, kapag nagpadala kami ng kahilingan /webproject/hello(kung saan ang /webproject ang context root), ang DispatcherServlet ay unang ipoproseso. Siya, bilang pangunahing dispatcher, ay tutukuyin na kami /* ay tumutugma sa kasalukuyang kahilingan, na nangangahulugan na ang DispatcherServlet ay dapat gumawa ng isang bagay. Pagkatapos ay dadaan ito sa lahat ng mga pagmamapa na mahahanap nito. Makikita nito na mayroong HelloController na may paraan ng paghawak na naka-map sa /hello at isasagawa ito. Ibabalik ng pamamaraang ito ang tekstong "hello". Ang tekstong ito ay matatanggap ng ViewResolver, na magsasabi sa server kung saan hahanapin ang mga jsp file na kailangang ipakita sa kliyente. Kaya, sa huli ay matatanggap ng kliyente ang napakamahal na pahinang iyon.

Konklusyon

Sana ay malinaw sa artikulo na ang salitang "konteksto" ay hindi nakakatakot. Ang mga pagtutukoy na iyon ay naging lubhang kapaki-pakinabang. At ang dokumentasyon ay ating kaibigan, hindi ang ating kaaway. Umaasa ako na magiging malinaw kung ano ang batayan ng Spring, kung paano ito kumokonekta, at kung ano ang kinalaman ng Servlet API dito.
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION