JavaRush /Java Blog /Random-TL /Panimula sa Maven, Spring, MySQL, Hibernate at ang unang ...
Макс
Antas

Panimula sa Maven, Spring, MySQL, Hibernate at ang unang CRUD application (part 2)

Nai-publish sa grupo
Magandang hapon. Sa artikulong ito nais kong ibahagi ang aking unang pagkikita sa mga bagay tulad ng Maven, Spring, Hibernate, MySQL at Tomcat sa proseso ng paglikha ng isang simpleng CRUD application. Ito ang pangalawang bahagi ng 4. Ang artikulo ay pangunahing inilaan para sa mga nakatapos na ng 30-40 na antas dito, ngunit hindi pa nakipagsapalaran sa kabila ng purong Java at nagsisimula pa lamang (o malapit nang magsimula) upang makapasok sa bukas na mundo na may lahat ng mga teknolohiyang ito, mga balangkas at iba pang hindi pamilyar na mga salita. Ito ang ikalawang bahagi ng artikulong "Introduction to Maven, Spring, MySQL, Hibernate at ang unang CRUD application." Ang unang bahagi ay makikita sa pamamagitan ng pagsunod sa link na ito: Panimula sa Maven, Spring, MySQL, Hibernate at ang unang CRUD application (part 1)

Nilalaman:

Buweno, magpatuloy tayo, subukan nating mag-conjure ng isang buong repository ng mga pelikula. Sa aming maliit at simpleng aplikasyon, siyempre, maaari mo lamang tanga na ilagay ang lahat ng lohika sa controller, ngunit, tulad ng nabanggit na, mas mahusay na agad na matutunan kung paano gawin ang lahat ng tama. Samakatuwid, gumawa tayo ng ilang mga layer. Magkakaroon kami ng DAO na responsable para sa pagtatrabaho sa data, isang Serbisyo , kung saan magkakaroon ng lahat ng uri ng iba pang lohika, at ang Controller ay magpoproseso lamang ng mga kahilingan at tatawag sa mga kinakailangang pamamaraan ng serbisyo.

Bagay sa Pag-access ng Data

Ang Data Access Object (DAO) ay isang pattern ng disenyo. Ang punto ay upang lumikha ng isang espesyal na layer na magiging tanging responsable para sa pag-access ng data (paggawa gamit ang isang database o iba pang mekanismo ng imbakan). Sa pakete daoay gagawa kami ng isang interface FilmDAOkung saan magkakaroon ng mga pamamaraan tulad ng magdagdag, magtanggal, atbp. Medyo naiiba ang tawag ko sa kanila, ngunit tumutugma sila sa mga pangunahing operasyon ng CRUD ( C reate, Read , U pdate, D elete).

Kapansin-pansin dito na bilang karagdagan sa DAO, mayroon ding isang diskarte tulad ng Repository, tila magkapareho sila, parehong ginagamit para sa pagtatrabaho sa data. Hindi ko pa naiisip kung ano ang mga tampok ng mga diskarteng ito at kung ano ang pagkakaiba sa pagitan nila. Samakatuwid, maaaring ako ay nagkakamali dito at dapat itong tawaging isang imbakan, at hindi isang Tao, o marahil ito ay isang bagay sa pagitan. Ngunit sa karamihan ng mga halimbawa na aking nakita at napag-aralan, ito ay tinatawag na DAO, kaya malamang na tatawagin ko ito. Kasabay nito, marahil sa isang lugar pa sa teksto ay gagamitin ko ang salitang repositoryo. Sa anumang kaso, kung ako ay mali sa isang lugar dito, mangyaring patawarin mo ako.

package testgroup.filmography.dao;

import testgroup.filmography.model.Film;

import java.util.List;

public interface FilmDAO {
    List<Film> allFilms();
    void add(Film film);
    void delete(Film film);
    void edit(Film film);
    Film getById(int id);
}
Ngayon kailangan natin ang pagpapatupad nito. Hindi pa namin ikokonekta ang database, medyo nakakatakot pa rin. Para magsanay at masanay, gayahin muna natin ang storage sa memorya at gumawa ng listahan na may ilang pelikula. Upang iimbak ang listahan, gagamitin namin ang hindi List, ngunit Map, upang gawing maginhawang kunin ang isang partikular na pelikula sa pamamagitan ng id, nang hindi dumadaan sa buong listahan. Para sa henerasyon idginagamit namin ang AtomicInteger . Gumawa tayo ng isang klase FilmDAOImpl, ipatupad ang lahat ng mga pamamaraan at punan ang mapa. May ganyan.
package testgroup.filmography.dao;

import testgroup.filmography.model.Film;

import java.util.*;

public class FilmDAOImpl implements FilmDAO {
    private static final AtomicInteger AUTO_ID = new AtomicInteger(0);
    private static Map<Integer, Film> films = new HashMap<>();

    static {
        Film film1 = new Film();
        film1.setId(AUTO_ID.getAndIncrement());
        film1.setTitle("Inception");
        film1.setYear(2010);
        film1.setGenre("sci-fi");
        film1.setWatched(true);
        films.put(film1.getId(), film1);

        // + film2, film3, film4, ...
    }
    @Override
    public List<Film> allFilms() {
        return new ArrayList<>(films.values());
    }

    @Override
    public void add(Film film) {
        film.setId(AUTO_ID.getAndIncrement());
        films.put(film.getId(), film);
    }

    @Override
    public void delete(Film film) {
        films.remove(film.getId());
    }

    @Override
    public void edit(Film film) {
        films.put(film.getId(), film);
    }

    @Override
    public Film getById(int id) {
        return films.get(id);
    }
}

Serbisyo

Ngayon magdagdag tayo ng layer ng serbisyo. Sa prinsipyo, sa halimbawang ito ay posible na gawin nang wala ito, nililimitahan ang ating sarili sa DAO; ang aplikasyon ay magiging napaka-simple at walang mga plano para sa anumang kumplikadong lohika sa serbisyo. Ngunit biglang, sa hinaharap, nais mong magdagdag ng lahat ng uri ng mga komplikasyon at mga kagiliw-giliw na bagay sa proyekto, kaya para sa kapakanan ng pagkakumpleto, hayaan ito. Sa ngayon, tatawag lang ito ng mga pamamaraan mula sa DAO. serviceGumawa tayo ng interface sa package FilmService.
package testgroup.filmography.service;

import testgroup.filmography.model.Film;

import java.util.List;

public interface FilmService {
    List<Film> allFilms();
    void add(Film film);
    void delete(Film film);
    void edit(Film film);
    Film getById(int id);
}
At ang pagpapatupad nito:
package testgroup.filmography.service;

import testgroup.filmography.dao.FilmDAO;
import testgroup.filmography.dao.FilmDAOImpl;
import testgroup.filmography.model.Film;

import java.util.List;

public class FilmServiceImpl implements FilmService {
    private FilmDAO filmDAO = new FilmDAOImpl();

    @Override
    public List<Film> allFilms() {
        return filmDAO.allFilms();
    }

    @Override
    public void add(Film film) {
        filmDAO.add(film);
    }

    @Override
    public void delete(Film film) {
        filmDAO.delete(film);
    }

    @Override
    public void edit(Film film) {
        filmDAO.edit(film);
    }

    @Override
    public Film getById(int id) {
        return filmDAO.getById(id);
    }
}
Ang istraktura ng proyekto ngayon ay ganito ang hitsura:
Panimula sa Maven, Spring, MySQL, Hibernate at ang unang CRUD application (part 2) - 1

Controller at Views

Gawin natin ngayon ang mga pamamaraan ng controller at punan ang mga pahina. Kapag pinupunan ang mga pahina, kakailanganin namin ng ilang mga diskarte. Halimbawa, upang magpakita ng isang listahan ng mga pelikula, kailangan namin ng isang cycle, kung, halimbawa, gusto naming baguhin ang ilang inskripsyon, depende sa mga parameter, kailangan namin ng mga kondisyon, atbp. Ang format ng JSP (JavaServer Pages) ay nagbibigay-daan sa iyo na gumamit ng mga pagsingit ng java code kung saan maipapatupad ang lahat ng ito. Ngunit ayaw kong gumamit ng java code na may halong HTML code sa page. Ito ay, sa pinakamababa, napakapangit. Sa kabutihang palad, upang malutas ang problemang ito ay mayroong napakagandang bagay tulad ng JSTL (JavaServer Pages Standard Tag Library) o ang JSP Standard Tag Library. Nagbibigay-daan ito sa amin na gumamit ng isang buong bungkos ng mga karagdagang tag sa aming mga pahina ng JSP para sa iba't ibang pangangailangan. Ikonekta natin ito sa pom.xml:
<dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
</dependency>
Ngayon tingnan natin ang controller. Una sa lahat, alisin natin ang paglikha ng bagay mula doon Film, ginawa ito para sa pagsubok at hindi na natin kailangan ng anupaman. Magdagdag tayo ng serbisyo doon at tawagan ang mga pamamaraan nito.
public class FilmController {
    private FilmService filmService = new FilmServiceImpl();
Kaya, naaayon ay gagawa kami ng mga pamamaraan para sa bawat kaso, magdagdag, magtanggal, atbp. Una ay isang paraan upang ipakita ang pangunahing pahina na may listahan ng mga pelikula:
@RequestMapping(method = RequestMethod.GET)
    public ModelAndView allFilms() {
        List<Film> films = filmService.allFilms();
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("films");
        modelAndView.addObject("filmsList", films);
        return modelAndView;
    }
Walang bago dito. Kumuha kami ng listahan ng mga pelikula mula sa serbisyo at idinagdag ito sa modelo. Ngayon gawin natin ang pangunahing pahina films.jspna ibinabalik ng pamamaraang ito:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>FILMS</title>
</head>
<body>

<h2>Films</h2>
<table>
    <tr>
        <th>id</th>
        <th>title</th>
        <th>year</th>
        <th>genre</th>
        <th>watched</th>
        <th>action</th>
    </tr>
    <c:forEach var="film" items="${filmsList}">
        <tr>
            <td>${film.id}</td>
            <td>${film.title}</td>
            <td>${film.year}</td>
            <td>${film.genre}</td>
            <td>${film.watched}</td>
            <td>
                <a href="/edit/${film.id}">edit</a>
                <a href="/delete/${film.id}">delete</a>
            </td>
        </tr>
    </c:forEach>
</table>

<h2>Add</h2>
<c:url value="/add" var="add"/>
<a href="${add}">Add new film</a>
</body>
</html>
Tingnan natin ang page na ito para makita kung ano. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - dito nakakonekta ang JSTL core, na kinabibilangan ng mga pangunahing tag para sa paglikha ng mga cycle, kundisyon, atbp .
  • <table>— tag para sa paggawa ng table.
  • <tr>— hilera ng mesa
  • <th>- header ng column
  • <td>- mesa cell
Una, gumawa kami ng row ng table header na may mga pangalan ng mga column. Pagkatapos <c:forEach var="film" items="${filmsList}">, sa isang loop (na kinuha namin mula sa JSTL core), dumaan kami sa lahat ng mga elemento ng naipasa na listahan ( filmsList), para sa bawat elemento ( film) lumikha kami ng bagong hilera at isulat ang kaukulang halaga sa bawat cell. Mayroong isang punto dito, ang pag-record ay tila film.idkailangang maunawaan bilang film.getId(), i.e. Ang field ay hindi direktang naa-access, ngunit ang getter ay tinatawag. Sa huling hanay ( action) gumagawa kami ng mga link para sa pagtanggal at pag-edit (gagawin namin ang mga kaukulang pamamaraan ngayon). Well, sa ibaba ay isang link sa paraan para sa pagdaragdag ng bagong pelikula. Narito kung ano ang hitsura nito: Susunod, tingnan natin ang paraan na magbabalik sa pahina ng pag-edit para sa isang partikular na pelikula:
@RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
    public ModelAndView editPage(@PathVariable("id") int id) {
        Film film = filmService.getById(id);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("editPage");
        modelAndView.addObject("film", film);
        return modelAndView;
    }
May bagong lumabas dito - isa itong anotasyon @PathVariable. Ipinapahiwatig nito na ang parameter na ito ( int id) ay nakuha mula sa address bar. Upang ipahiwatig ang lokasyon ng parameter na ito sa address bar, ginagamit ang konstruksiyon {id}(sa pamamagitan ng paraan, kung ang variable na pangalan ay pareho, tulad ng sa kasong ito, hindi mo kailangang ipahiwatig ito sa mga panaklong, ngunit isulat lamang ito @PathVariable int id). Kaya, sa pangunahing pahina gumawa kami ng mga link para sa bawat pelikula na nagsasaad ng id:
<a href="/edit/${film.id}">edit</a>
Pagkatapos ang halagang ito ay itinalaga sa parameter ng pamamaraan at pagkatapos ay ginagamit namin ito upang makakuha ng isang partikular na pelikula mula sa repositoryo sa pamamagitan ng serbisyo at idagdag ito sa modelo. Ito ang paraan para makuha ang pahina ng pag-edit, ngayon kailangan namin ng isang paraan para sa pag-edit mismo:
@RequestMapping(value = "/edit", method = RequestMethod.POST)
    public ModelAndView editFilm(@ModelAttribute("film") Film film) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("redirect:/");
        filmService.edit(film);
        return modelAndView;
    }
Sa paraang editPagenagdagdag kami ng isang katangian sa modelo:
modelAndView.addObject("film", filmService.getById(id));
At ngayon, sa tulong ng anotasyon, @ModelAttributenakukuha natin ang katangiang ito at mababago natin ito. Request method POSTkasi dito natin ipapasa ang data. Ang ibig sabihin ng " redirect:/" ay pagkatapos isagawa ang paraang ito ay ire-redirect tayo sa address na " /", ibig sabihin. tatakbo ang pamamaraan allFilmsat babalik tayo sa pangunahing pahina. Ngayon gawin natin ang pahina mismo editPage.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Edit</title>
</head>
<body>
<c:url value="/edit" var="var"/>
<form action="${var}" method="POST">
    <input type="hidden" name="id" value="${film.id}">
    <label for="title">Title</label>
    <input type="text" name="title" id="title">
    <label for="year">Year</label>
    <input type="text" name="year" id="year">
    <label for="genre">Genre</label>
    <input type="text" name="genre" id="genre">
    <label for="watched">Watched</label>
    <input type="text" name="watched" id="watched">
    <input type="submit" value="Edit film">
</form>
</body>
</html>
  • <form>— isang form para sa pagkolekta at pagpapadala ng data, na nagpapahiwatig kung sino ang magpoproseso nito ( /edit)
  • <input>— mga elemento ng interface para sa pakikipag-ugnayan ng user (mga button, input field, atbp.)
  • <label>- label ng teksto
Kaya, kapag na-click mo ang pindutan, <input type="submit" value="Edit film">ang data mula sa form ay ipapadala sa server (isang hindi nakikitang field na may halaga ay espesyal na idinagdag idupang malaman ng server kung aling talaan sa database ang kailangang i-update). Sa paraang editFilmitatalaga sila sa kaukulang mga patlang ng katangian film. Pagkatapos ay babalik kami sa pangunahing pahina na may na-update na listahan. Ang pahina ng pag-edit ay ganito ang hitsura: Ngayon simulan natin ang pagdaragdag ng mga bagong pelikula sa listahan. Upang gawin ito, kakailanganin mo rin ng isang form para sa pagpasok at pagsusumite ng data. Maaari kang gumawa ng isang form sa pangunahing pahina o maaari kang gumawa ng isang hiwalay na pahina, tulad ng editPage.jsp. Ngunit, sa kabilang banda, ang form para sa pagdaragdag ay magiging eksaktong kapareho ng para sa pag-edit, i.e. 4 na input field at isang submit button. Kaya bakit lumikha ng isang bagong pahina kung gayon, gamitin natin ang editPage.jsp. Paraan para makuha ang page:
@RequestMapping(value = "/add", method = RequestMethod.GET)
    public ModelAndView addPage() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("editPage");
        return modelAndView;
    }
Sa pamamaraan, editPageidinagdag namin ang katangian upang mabago ito sa ibang pagkakataon, ngunit dito lang namin natatanggap ang pahina. At ang paraan upang magdagdag:
@RequestMapping(value = "/add", method = RequestMethod.POST)
    public ModelAndView addFilm(@ModelAttribute("film") Film film) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("redirect:/");
        filmService.add(film);
        return modelAndView;
    }
Dahil hindi namin naipasa ang attribute dito, isang bagong object ang gagawin dito Film. Well, wala namang bago dito. Dapat ding tandaan na mayroon kaming parehong mga pamamaraan na magagamit sa " /add". Posible ito dahil sa katotohanang tumutugon sila sa iba't ibang uri ng mga kahilingan. Sa pamamagitan ng pagsunod sa link sa pangunahing pahina gumawa kami ng isang kahilingan sa GET, na humahantong sa amin sa addPage. At kapag sa pagdaragdag ng pahina ay nag-click kami sa pindutan upang magpadala ng data, isang kahilingan sa POST ang ginawa, at ang addFilm. Upang magdagdag ng bagong pelikula, napagpasyahan naming gamitin ang parehong pahina sa pag-edit. Ngunit doon ipinadala ang data sa address na " /edit":
<c:url value="/edit" var="var"/>
<form action="${var}" method="POST">
    <input type="submit" value="Edit film">
</form>
Kailangan nating i-tweak nang kaunti ang pahina upang ito ay kumilos nang iba para sa pagdaragdag at pag-edit. Upang malutas ang isyung ito, gagamitin namin ang mga kundisyon mula sa parehong JSTL core library:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <c:if test="${empty film.title}">
        <title>Add</title>
    </c:if>
    <c:if test="${!empty film.title}">
        <title>Edit</title>
    </c:if>
</head>
<body>
<c:if test="${empty film.title}">
    <c:url value="/add" var="var"/>
</c:if>
<c:if test="${!empty film.title}">
    <c:url value="/edit" var="var"/>
</c:if>
<form action="${var}" method="POST">
    <c:if test="${!empty film.title}">
        <input type="hidden" name="id" value="${film.id}">
    </c:if>
    <label for="title">Title</label>
    <input type="text" name="title" id="title">
    <label for="year">Year</label>
    <input type="text" name="year" id="year">
    <label for="genre">Genre</label>
    <input type="text" name="genre" id="genre">
    <label for="watched">Watched</label>
    <input type="text" name="watched" id="watched">
    <c:if test="${empty film.title}">
        <input type="submit" value="Add new film">
    </c:if>
    <c:if test="${!empty film.title}">
        <input type="submit" value="Edit film">
    </c:if>
</form>
</body>
</html>
Yung. sinusuri lang namin ang field film.title. Kung ito ay walang laman, kung gayon ito ay isang bagong pelikula, dapat nating punan ang lahat ng data para dito at idagdag ito sa listahan. Kung walang laman ang field na ito, ito ay isang pelikula mula sa listahan at kailangan mo lang itong baguhin. yun. nakakakuha kami ng dalawang bersyon ng aming page: Well, ang huling paraan ng controller para sa pag-alis ng pelikula mula sa listahan:
@RequestMapping(value="/delete/{id}", method = RequestMethod.GET)
    public ModelAndView deleteFilm(@PathVariable("id") int id) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("redirect:/");
        Film film = filmService.getById(id);
        filmService.delete(film);
        return modelAndView;
    }
Sa tingin ko hindi na kailangang magkomento ng anuman dito, lahat ng ito ay napag-isipan na. Nakagawa na kami ng mga link sa address na ito sa pangunahing pahina. Well, mukhang handa na ang lahat dito, maaari mo itong patakbuhin muli at makita kung paano gumagana ang lahat.

Imbakan at Serbisyo bilang Mga Bahagi ng Spring

Gumawa tayo ng isa pang maliit na pagwawasto. Ang katotohanan ay ngayon ang aming imbakan at serbisyo ay mga klase lamang, at upang magamit ang mga ito kailangan naming lumikha ng isang object ng klase sa aming sarili ( new FilmServiceImpl()). Ngunit mayroon kaming Spring konektado para sa isang dahilan , kaya hayaan siyang kontrolin ang bagay na ito sa kanyang sarili. Upang ilagay ang aming mga klase sa ilalim ng kontrol ng Spring, kailangan naming ipahiwatig na ang mga ito ay mga bahagi. Upang gawin ito, markahan namin sila ng mga espesyal na anotasyon:
@Repository
public class FilmDAOImpl implements FilmDAO {
@Service
public class FilmServiceImpl implements FilmService {
Mga anotasyon @Repositoryat @Service, gayundin @Controlleray nagmula sa @Component. Ano ang mga partikular na tampok at pagkakaiba ng tatlong anotasyong ito at kung paano sila naiiba sa isang simpleng bahagi ay dapat basahin nang hiwalay sa dokumentasyon o mga gabay. Sa ngayon, sapat na na malaman na ang mga anotasyong ito ay nagsasabi sa Spring na ang mga klase na ito ay isang repositoryo at isang serbisyo, ayon sa pagkakabanggit. At ngayon hindi na natin kailangang lumikha ng mga konkretong bagay ng mga klaseng ito sa ating sarili:
private FilmService filmService = new FilmServiceImpl();
Sa halip, maaari mong markahan ang field ng isang espesyal na anotasyon at pipiliin ng Spring ang naaangkop na pagpapatupad:
@Autowired
private FilmService filmService;
Ang anotasyon @Autowired(auto-binding) ay nagsasabi sa Spring na dapat itong maghukay sa konteksto nito at palitan ang isang angkop na bean dito. Napakakomportable. Kung dati ay gumamit kami ng mga interface upang hindi mag-alala tungkol sa partikular na pagpapatupad ng mga pamamaraan, ngayon ay hindi na namin kailangang mag-alala tungkol sa pagpapatupad ng interface mismo at kahit na alam ang pangalan nito. Ang ideya ay hindi inirerekomenda na gumamit ng auto-binding sa isang field; mas mainam na gumamit ng constructor o setter. Magbasa nang higit pa tungkol dito sa dokumentasyon. Para sa amin, sa prinsipyo, ito ay hindi mahalaga, maaari naming ligtas na iwanan ito nang ganoon. Ngunit, dahil hinihiling ito ng ideya, igagalang namin na ang lahat ay maganda at walang anumang dilaw na babala. Sa controller class, gumawa tayo ng setter at i-annotate ito:
@Controller
public class FilmController {

    private FilmService filmService;

    @Autowired
    public void setFilmService(FilmService filmService) {
        this.filmService = filmService;
    }
At katulad din gumawa kami ng setter para FilmDAOsa klase FilmServiceImpl. 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)
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION