Nilalaman:
- Panimula
- Paglikha ng isang Proyekto
- Koneksyon ng Spring MVC
- Paglikha ng Mga Pahina at Controller
- Configuration
- Modelo
- Model-View-Controller
Panimula
Nagsimula akong makilala ang mga teknolohiya at balangkas na bago sa akin sa pamamagitan ng pag-aaral ng iba't ibang mga halimbawa kung saan ginamit ang mga ito, dahil kadalasan ay mas naiintindihan ko ang isang bagay kapag nakikita ko ito sa pagkilos gamit ang isang halimbawa ng isang ganap na aplikasyon. Kadalasan, ang mga ganitong halimbawa ay mga CRUD application ( C reate, Read , U pdate, D elete), ang Internet ay puno ng mga ganitong halimbawa ng iba't ibang antas ng pagiging kumplikado. Ang problema ay kadalasang hindi nila ipinapaliwanag nang detalyado kung paano, ano at bakit ginawa doon, bakit idinagdag ang ganoon at ganoong dependency, bakit kailangan ang ganoon at ganoong klase, atbp. Sa karamihan ng mga kaso, kumukuha sila ng isang ganap na natapos na aplikasyon, na may panghuling POM file, na may mga huling bersyon ng mga klase, at simpleng tumatakbo sa bawat isa, nang hindi tumutuon sa maliliit na bagay na malamang na halata sa isang may karanasang tao. Tumingin ako sa maraming tulad na mga halimbawa at kadalasan ay malinaw kung paano gumagana ang lahat, ngunit kung paano sila nakarating dito ay hindi lubos na malinaw. Samakatuwid, napagpasyahan ko na ang gayong halimbawa ay magiging kapaki-pakinabang, hindi mula sa posisyon ng isang may karanasan na developer, ngunit mula sa posisyon ng isang baguhan na hindi pa nakikitungo sa Spring, Hibernate at iba pang mga bagay.Paglikha ng isang Proyekto
Kaya, dahil ako ay isang baguhan, hindi kami gagamit ng anumang hindi malinaw na archetypes. Masyadong nakakatakot ang Spring initializr. Samakatuwid, gagawa kami ng pinakakaraniwang simpleng proyekto ng Maven. Wala akong domain name, kaya sa groupid na lang ako magsusulattestgroup
, at sa artifactid isusulat ko ang pangalan, halimbawa, filmography
(ito ay magiging isang listahan ng mga pelikula). Gumagawa kami ng proyekto at pinipili Enable auto-import
kung kailan ito iminumungkahi ng ideya. Salamat dito, sa bawat oras na gumawa kami ng anumang mga pagbabago sa POM file (Project Object Model, ang file na ito ay naglalarawan sa buong istraktura ng Maven project), lahat ay awtomatikong mailalapat sa proyekto. Ang mga aklatan ay kukunin mula sa aming lokal na imbakan kung mayroon na kami ng mga ito, o kung gagamit kami ng ilang mga bagong dependency na hindi pa namin napag-uusapan noon, ida-download lang ito ni Maven sa pamamagitan ng Internet mula sa gitnang imbakan. Ang Maven ay mayroon ding function na mag-download ng mga source at dokumentasyon (Download Sources at/o Documentation). Napakaginhawa rin nito, kung may hindi malinaw sa ilang klase o pamamaraan, maaari kang pumunta sa source code at tingnan kung paano gumagana ang lahat sa loob. Magdagdag tayo ng ilang detalye. Ito ay magiging isang web application at gagamitin namin ang Tomcat . Upang mag-deploy ng isang application sa Tomcat, kailangan mong ilipat ito doon sa anyo ng isang archive ng digmaan (Web Application Resource, isang espesyal na format para sa mga web application). Upang gawin ito, idagdag ang sumusunod na linya sa POM file upang ang application ay naipon sa isang archive ng digmaan:
<packaging>war</packaging>
Well, kakailanganin mo rin ng isang espesyal na direktoryo para sa mga mapagkukunan ng web, sa aming kaso magkakaroon ng mga pahina ng jsp at ilang mga mapagkukunan sa web. Gumawa tayo ng isang main
direktoryo webapp
. Dapat itong tawagin nang eksakto at matatagpuan sa eksaktong main
parehong paraan tulad ng java
, resources
dahil ito ang karaniwang istraktura ng direktoryo ng Maven. Kapag na-install na namin ang package war
at sa gayon ay natukoy na ito ay isang web project, ang direktoryo webapp
ay awtomatikong mamarkahan bilang mga mapagkukunan ng Web application (magkakaroon ng asul na tuldok dito) at lahat ng nauugnay sa web ay hahanapin sa folder na ito. At isang sandali. Bilang default, gumagamit si Maven ng wikang bersyon 1.5, ngunit gusto kong gamitin, halimbawa, bersyon 1.8 - Java 8 (Maaari kang kumuha ng 10, o 11, ngunit wala pa ring planong gumamit ng anumang mga tampok mula doon, kaya hayaan itong maging 8 ). Ito ay malulutas nang napakasimple, nagsusulat kami sa Google ng isang bagay tulad ng "Maven java 8" at tingnan kung ano ang kailangang idagdag sa POM file upang ma-compile ng Maven ang aming mga klase para sa kinakailangang bersyon. Bilang resulta, mayroon kaming mga sumusunod:
Koneksyon ng Spring MVC
Kailangan mong magsimula sa isang lugar. Ayon sa plano, ikokonekta namin ang database at gagamitin ang Hibernate, ngunit ang lahat ng ito ay medyo nakakatakot sa ngayon. Kailangan muna nating gumawa ng mas simple. Spring MVC, ito ay mas mahusay, kami ay pamilyar sa pattern ng MVC sa loob ng mahabang panahon, ginamit ito sa kalahati ng malalaking gawain ng kurso. Mula dito ay magsisimula na tayong sumayaw. Para gumawa ng web application gamit ang Spring MVC, kailangan din namin ng Servlet-API, i.e. ang bagay na iyon sa tulong kung saan magaganap ang pakikipag-ugnayan ng kahilingan-tugon. Subukan nating ikonekta ito. Pumunta kami sa Google, hanapin ang mga kinakailangang dependency sa repositoryo ng Maven at idagdag ang mga ito sapom.xml
. Sa seksyong Mga Panlabas na Aklatan makikita mo na hindi lang spring-webmvc ang na-load , kundi pati na rin ang isang grupo ng iba pang mga bagay. Yung. hindi namin kailangang isama ang mga dependencies para sa spring core , context , beans , atbp. na kailangan namin, lahat ng kailangan namin ay nakuha kasama ng spring-webmvc .
Kailangan nating gumawa ng isang maliit na disclaimer. Karaniwang inirerekomenda na magdagdag pa rin ng dependency nang hiwalay para sa bawat library na ginamit, kahit na naka-bundle na ang mga ito sa mga naidagdag na, dahil makakatulong ito na maiwasan ang ilang problema at aberya. Isang simpleng halimbawa. Sabihin nating nagdagdag kami ng dependency na gumagamit ng ilang API, at sa parehong oras ay kukuha ito ng ilang uri ng pagpapatupad para sa API na ito. At pagkatapos ay nagdagdag kami ng isa pang dependency na gumagamit ng parehong API at kinukuha din ang ilan sa pagpapatupad nito para dito, ngunit sa pagkakataong ito ay iba na. Kaya, magkakaroon tayo ng 2 magkaibang pagpapatupad ng parehong API. At kung gusto nating gumamit ng ilang mga pamamaraan ng API na ito sa isang lugar, magkakaroon ng problema, dahil hindi malalaman ng system kung aling pagpapatupad ang gagamitin, pipili ito nang random, marahil hindi ang inaasahan natin. At kung tahasan mong tinukoy ang isang dependency para sa isa sa mga pagpapatupad, pagkatapos ay ibibigay ang priyoridad dito. Gayunpaman, hindi ito isang mahigpit na rekomendasyon; ito ay pangunahing nalalapat sa malalaking proyekto kung saan maraming iba't ibang mga aklatan mula sa iba't ibang kumpanya ang ginagamit. Hindi namin gagawin iyon dito, para hindi masyadong ma-load ang POM file; walang inaasahang problema. Ngunit gayunpaman, ito ay nagkakahalaga pa rin na isaisip ito. |
provided
ng depende javax.servlet-api
? Ang saklaw ay ang saklaw ng dependency, provided
na nangangahulugan na ang dependency ay magiging available sa yugto ng pag-compile at pagsubok ng application, ngunit hindi ito ia-archive. Ang katotohanan ay upang i-deploy ang application ay gagamit kami ng isang servlet container, Tomcat, at mayroon na itong mga library sa loob, kaya hindi na kailangang ilipat ang mga ito doon at pasanin ang archive ng hindi kinakailangang pag-load. Sa hinaharap, para sa parehong dahilan ay gagawin namin nang wala ang karaniwang pamamaraan main
, dahil mayroon na itong nasa loob ng Tomcat.
Paglikha ng Mga Pahina at Controller
Subukan nating magluto ng simple ngayon. Una, gumawa tayo ngwebapp
karagdagang direktoryo, halimbawa pages
, kung saan maiimbak ang ating mga view, i.e. jsp na pahina, at lumikha ng ilang pahina. Kakailanganin namin ang isang pahina kung saan sa hinaharap ang isang listahan ng mga pelikula ay ipapakita, halimbawa films.jsp
, at marahil ay maaari kaming gumawa ng isang hiwalay na pahina para sa pag-edit, hayaan ito editPage.jsp
. Hindi namin sila pupunuan ng anumang seryoso sa ngayon; para lamang sa pagsubok, gagawa kami ng link sa isang pahina patungo sa isa pa. Ngayon kailangan namin ng isang klase na magpoproseso ng mga kahilingan, i.e. controller. Magdagdag tayo ng isang bagong pakete controller
at lumikha ng isang klase sa loob nito FilmController
(sa pangkalahatan, hindi kinakailangan na i-package ang lahat sa iba't ibang mga pakete, ang application na ito ay magiging napakaliit at simple, ngunit sa isang normal na proyekto ay maaaring magkaroon ng maraming mga controller, mga klase ng pagsasaayos, mga modelo , at iba pa, kaya kahit na nagsisimula sa maliliit na proyekto, mas mainam na agad na masanay na gawin ang lahat sa maayos at balangkas na paraan upang walang gulo). Sa klase na ito gagawa kami ng mga pamamaraan na magbabalik sa aming mga pananaw bilang tugon sa mga kahilingan.
package testgroup.filmography.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class FilmController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView allFilms() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("films");
return modelAndView;
}
@RequestMapping(value = "/edit", method = RequestMethod.GET)
public ModelAndView editPage() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("editPage");
return modelAndView;
}
}
Ano ang punto? Ang Spring MVC ay may tinatawag na DispatcherServlet
. Ito ay tulad ng pangunahing controller, lahat ng mga papasok na kahilingan ay dumadaan dito at pagkatapos ay ipinapasa ang mga ito sa isang partikular na controller. Sinasabi lang ng anotasyon @Controller
sa Spring MVC na ang klase na ito ay isang controller (well, lohikal sa pangkalahatan), susuriin ng dispatcher ang mga anotasyon @RequestMapping
upang tawagan ang naaangkop na pamamaraan. Binibigyang-daan ka ng anotasyon @RequestMapping
na tumukoy ng mga address para sa mga pamamaraan ng controller, kung saan magiging available ang mga ito sa client (browser). Maaari rin itong ilapat sa klase ng controller upang itakda, wika nga, ang root address para sa lahat ng mga pamamaraan. allFilms()
Ang parameter para sa pamamaraan value
ay nakatakda sa " /
", kaya agad itong tatawagin kapag ang kumbinasyong http://host:port/ ay ipinasok sa browser (i.e., bilang default, ito ay http://localhost:8080/ o http ://127.0 .0.1:8080/ ). method
Tinutukoy ng parameter kung anong uri ng kahilingan ang sinusuportahan (GET, POST, PUT, atbp.). Dahil dito lang kami tumatanggap ng data, GET ang ginagamit. Sa ibang pagkakataon, kapag lumitaw ang mga paraan para sa pagdaragdag at pag-edit, magkakaroon na ng mga kahilingan sa POST. (Siya nga pala, sa halip na isang anotasyon @RequestMapping
na nagsasaad ng isang paraan, maaari mong gamitin ang mga anotasyon @GetMapping
, @PostMapping
atbp. @GetMapping
nang katumbas @RequestMapping(method = RequestMethod.GET
)). Sa aming mga pamamaraan, lumikha kami ng isang bagay ModelAndView
at itinakda ang pangalan ng view na kailangang ibalik.
Configuration
Magpatuloy tayo sa pagse-set up ng configuration.config
Gumawa tayo ng klase sa package WebConfig
. Magkakaroon lamang ito ng isang paraan na nagbabalik ng isang object ng uri ViewResolver
, ito ang interface na kinakailangan upang makahanap ng representasyon ayon sa pangalan.
package testgroup.filmography.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "testgroup.filmography")
public class WebConfig {
@Bean
ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
@Configuration
ay nagsasabi sa Spring na ang klase na ito ay isang klase ng pagsasaayos at naglalaman ng mga kahulugan at dependency bean
ng mga bahagi. Ang mga bean ay mga bagay na pinamamahalaan ng Spring. Ang anotasyon ay ginagamit upang tukuyin ang isang bean @Bean
. @EnableWebMvc
ay nagbibigay-daan sa iyo na mag-import ng Spring MVC configuration mula sa WebMvcConfigurationSupport
. Maaari mo ring ipatupad, halimbawa, ang isang interface WebMvcConfigurer
na may isang buong grupo ng mga pamamaraan, at i-customize ang lahat ayon sa gusto mo, ngunit hindi pa namin kailangang pumunta doon, ang mga karaniwang setting ay sapat na. @ComponentScan
nagsasabi sa Spring kung saan hahanapin ang mga sangkap na dapat nitong pamahalaan, ibig sabihin. mga klase na minarkahan ng annotation @Component
o mga derivatives nito gaya ng @Controller
, @Repository
, @Service
. Awtomatikong tinutukoy ng mga anotasyong ito ang class bean. Sa pamamaraan, viewResolver()
ginagawa namin ang pagpapatupad nito at tinutukoy kung saan eksaktong hahanapin ang mga representasyon sa webapp
. Samakatuwid, kapag sa paraan ng controller ay itinakda namin ang pangalan na " films
" ang view ay makikita bilang " /pages/films.jsp
" Kaya, mayroon kaming isang klase ng pagsasaayos, ngunit sa ngayon ito ay isang uri ng hiwalay na klase, hindi ito nakakaapekto sa aming aplikasyon sa anumang paraan . Kailangan nating irehistro ang pagsasaayos na ito sa konteksto ng Spring. Para dito kailangan mo ng isang klase AbstractAnnotationConfigDispatcherServletInitializer
. Sa package, config
ginagawa namin ang kapalit nito, sabihin AppInitializer , at ipinapatupad ang mga pamamaraan nito.
package testgroup.filmography.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
Ang huling paraan ay nagrerehistro ng mga address at mayroong 2 pang pamamaraan para sa pagrerehistro ng mga klase ng pagsasaayos. Ang mga configuration sa web, kung saan ViewResolver
tinukoy ang 's at ang katulad nito, ay inilalagay sa getServletConfigClasses()
. Mas mainam na basahin ang tungkol sa lahat ng ito sa dokumentasyon at iba't ibang mga gabay, ngunit sa aming kaso ay hindi pa kinakailangan na bungkalin ito, ang atin, WebConfig
sa prinsipyo, ay maaaring RootClasses
tukuyin sa pareho, maaari mo ring tukuyin ang pareho nang sabay-sabay, gagana pa rin ito. . Isa pang bagay. Maaaring may mga problema sa pag-encode kapag, kapag nagpapadala ng mga halaga na may mga character na Ruso mula sa form, ang resulta ay mga scribbles. Upang malutas ang problemang ito, magdaragdag kami ng isang filter na paunang magpoproseso ng mga kahilingan. Pumunta kami sa klase ng AppInitializer at i-override ang pamamaraan getServletFilters
, kung saan ipinapahiwatig namin ang nais na pag-encode, siyempre, dapat itong pareho sa lahat ng lugar, tulad ng sa mga pahina at sa database:
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return new Filter[] {characterEncodingFilter};
}
Buweno, ang lahat ay tila naka-set up, maaari mong subukang patakbuhin ito at makita kung ano ang mangyayari. Run -> Run -> Edit Configurations -> Add New Configuration -> Tomcat Server -> Local Susunod, kailangan mong pumili ng artifact na i-deploy. Ang ideya mismo ay magbibigay ng pahiwatig Babala: Walang mga artifact na minarkahan para sa pag-deploy . I-click ang fix button at piliin ang ...: war exploded . O maaari kang pumunta sa Deployment -> add -> Artifact -> ...: war exploded . At kailangan mo ring pumunta sa Deployment at itakda ang field ng konteksto ng Applecation (ito ay magiging bahagi ng url address kung saan magiging available ang application sa browser) sa " /
". Pagkatapos ay magiging available kaagad ang aming aplikasyon sa http://localhost:8080/ (ngunit maaari mo ring tukuyin ang isang bagay doon, halimbawa " /filmography
", at pagkatapos ay kakailanganin mo lamang itong idagdag sa lahat ng mga address, ibig sabihin, hindi magkakaroon ng " http://localhost:8080/edit" , ngunit ito ay magiging "http://localhost:8080/filmography/edit" ). I-click ang Run at maghintay hanggang magsimula ito. Narito ang nakuha ko: Mukhang maayos ang lahat, ngunit may isang babala. Ang katotohanan ay ang aming mga pahina ay naa-access na ngayon ng publiko at maaaring direktang ma-access sa pamamagitan ng pagsulat ng landas sa address bar. Pumasok kami sa http://localhost:8080/pages/films.jsp at ngayon ay natanggap na namin ang aming page nang hindi nalalaman ng controller. Kahit papaano ay hindi ito masyadong tama, kaya gagawa kami ng isang webapp
espesyal na direktoryo WEB-INF
. Ang nasa loob ay itatago sa publiko at maa-access lamang sa pamamagitan ng controller. Inilalagay namin ang direktoryo kasama ang aming mga view ( pages
) sa WEB-INF
, at ViewResolver
naaayon ay idinagdag ito sa prefix:
viewResolver.setPrefix("/WEB-INF/pages/");
Ngayon ay nakukuha namin ang aming pahina sa http://localhost:8080 , ngunit kung susubukan namin nang direkta sa http://localhost:8080/WEB-INF/pages/films.jsp nakakakuha kami ng 404 error. Well, mahusay, mayroon kaming pinakasimpleng web -application, Hello World gaya ng sinasabi nila. Ang istraktura ng proyekto ay kasalukuyang ganito:
Modelo
Mayroon na kaming mga view at controller, ngunit sa MVC mayroon ding 3rd letter, kaya upang makumpleto ang larawan ay magdaragdag din kami ng isang modelo. Sa package,model
gumawa tayo ng class Film
, halimbawa, na may mga sumusunod na field: int id
, String title
(title), int year
(year of release), String genre
(genre) at boolean watched
(i.e. napanood mo na ba ang pelikulang ito o hindi).
package testgroup.filmography.model;
public class Film {
private int id;
private String title;
private int year;
private String genre;
private boolean watched;
// + Getters and setters
}
Walang espesyal, ordinaryong klase lang, pribadong field, getter at setter. Ang mga bagay ng naturang mga klase ay tinatawag ding POJO
(Plain Old Java Object), well, i.e. "simpleng java object". Subukan natin ngayon na lumikha ng ganoong bagay at ipakita ito sa pahina. Sa ngayon, hindi kami masyadong mag-aalala tungkol sa kung paano ito gagawin at simulan ito. Upang subukan ito, gawin natin ito nang walang kabuluhan nang direkta sa controller, halimbawa, tulad nito:
public class FilmController {
private static Film film;
static {
film = new Film();
film.setTitle("Inception");
film.setYear(2010);
film.setGenre("sci-fi");
film.setWatched(true);
}
At idagdag ang bagay na ito sa atin ModelAndView
gamit ang pamamaraan addObject
:
@RequestMapping(method = RequestMethod.GET)
public ModelAndView allFilms() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("films");
modelAndView.addObject("film", film);
return modelAndView;
}
Ngayon ay maaari naming ipakita ang bagay na ito sa aming pahina. Sa films.jsp
halip na Hello World kami ay magsusulat ${film}
at ang bagay na nauugnay sa pangalan ng katangian na " film
" ay papalitan dito. Subukan nating patakbuhin ito at tingnan kung ano ang nangyari (para sa malinaw na output ng object, ang klase Film
ay muling tinukoy toString()
):
Model-View-Controller
Sa yugtong ito, tila mayroon na tayong ganap na Spring MVC application. Bago magpatuloy, makabubuting tingnan muli ang lahat at alamin kung paano gumagana ang lahat. Sa Internet maaari kang makahanap ng maraming mga larawan at mga diagram tungkol dito, gusto ko ang isang ito:Dispatcher Servlet
, pagkatapos ay nakahanap ito ng angkop na controller para iproseso ang kahilingang ito gamit ang HandlerMapping
(ito ay isang interface para sa pagpili ng controller, sinusuri kung alin sa mga available na controller ang may paraan na tumatanggap ng ganoong address) , ay tumatawag ng angkop na paraan at Controller
nagbabalik ng impormasyon tungkol sa view, pagkatapos ay hahanapin ng dispatcher ang nais na view sa pamamagitan ng pangalan gamit ang ViewResolver
'a, pagkatapos nito ay ililipat ang data ng modelo sa view na ito at makuha namin ang aming page bilang output. Isang bagay na tulad nito. Itutuloy... Ipinapakilala ang Maven, Spring, MySQL, Hibernate at ang unang CRUD application (part 1) Introducing Maven, Spring, MySQL, Hibernate at ang unang CRUD application (part 2) Introducing Maven, Spring, MySQL, Hibernate at ang unang CRUD application (bahagi 3) Panimula sa Maven, Spring, MySQL, Hibernate at ang unang CRUD application (bahagi 4)
GO TO FULL VERSION