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 (bahagi 4)

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 huling bahagi. Ang artikulo ay pangunahing inilaan para sa mga nakakumpleto na ng 30-40 na antas dito, ngunit hindi pa nakipagsapalaran sa kabila ng purong Java at nagsisimula pa lamang (o malapit nang magsimula) na pumasok sa bukas na mundo kasama ang lahat ng mga teknolohiyang ito, mga balangkas at iba pang hindi pamilyar na mga salita . Ito ang panghuling ikaapat na bahagi ng artikulong "Introduction to Maven, Spring, MySQL, Hibernate at ang unang CRUD application." Ang mga nakaraang bahagi ay makikita sa pamamagitan ng pagsunod sa mga link:

Nilalaman:

Disenyo at mga mapagkukunan sa web

Gumagana ang aming application, ngunit hindi mo ito matingnan nang walang luha, mga nakakainip na inskripsiyon, pangit na mga link, walang laman na puting background. Kailangan nating ayusin ito at magdagdag ng iba't ibang kagandahan. Paano natin ito gagawin? Well, una sa lahat, maaari mo lamang paglaruan ang mga pahina at gawin ang lahat ng uri ng mga bagay gamit ang mga kakayahan ng HTML . Ngunit kung susubukan mong baguhin ang mga background, kulay, laki, pag-aayos ng mga elemento, atbp gamit ang HTML lamang. at iba pa. pagkatapos ay sa huli ay makakagawa ka ng ganoong gulo sa pahina na hindi mo makikita ang anumang bagay doon mamaya. At bukod pa, ang mga pagpipilian sa disenyo ng HTML ay medyo limitado. Mas mainam na gumamit ng CSS (Cascading Style Sheets) para dito . Pagkatapos ang lahat ng nauugnay sa disenyo ay maaaring kolektahin sa isang lugar, at pagkatapos ay ilapat sa nais na elemento ng pahina. Ang CSS code ay maaaring isulat nang direkta sa JSP page sa isang espesyal na tag, ngunit ito ay mas maginhawa upang ilagay ito sa isang hiwalay na file, at pagkatapos ay ilapat lamang ito sa mga kinakailangang pahina. Upang maglagay ng mga file na may mga istilo at iba pang static na mapagkukunan ng web, gagawa kami ng hiwalay na direktoryo sa loob ng webapp . Upang hindi malito ang mga mapagkukunan ng web sa mga regular na mapagkukunan (kung saan mayroon tayong db.properties ), tawagan lang natin ang direktoryo na ito at ilagay ang lahat ng CSS file, larawan, atbp. doon:
Знакомство с Maven, Spring, MySQL, Hibernate и первое CRUD приложение (часть 4) - 1
Whatбы использовать эти файлы нам нужно указать их расположение в конфигурации. Идем в наш класс WebConfig. Ранее мы использовали аннотацию @EnableWebMvc чтобы ничего не настраивать, а просто использовать дефолтную конфигурацию. Но теперь возникла необходимость кое-что настроить. Для этого используем интерфейс WebMvcConfigurer, который позволяет переопределять методы конфигурации. Т.о. мы можем использовать конфигурацию по-умолчанию, но при этом некоторые моменты настроить под себя. В данном случае нам нужен метод addResourceHandlers, с помощью которого укажем расположение статических веб-ресурсов. На всякий случай весь класс целиком в итоге выглядит так:
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.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "testgroup.filmography")
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/res/**").addResourceLocations("/res/");
    }

    @Bean
    ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/pages/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
}
Теперь чтобы использовать наш CSS на странице нужно сделать на него ссылку внутри тега head:
<head>
    <link href="<c:url value="/res/style.css"/>" rel="stylesheet" type="text/css"/>
</head>
Достаточно добавить эту строчку и сделать, например, вот такой вот простенький CSS файл:
table {
    border-spacing: 0 10px;
    font:  bold 100% Georgia, serif;
    margin: 40px auto;
    text-shadow: 5px 5px 5px #3F3F7F;
    background: #B1B9D9;
    text-align: center;
    vertical-align: middle;
    width: 50%;
    border: 10px solid blue;
}
И это уже fully изменит нашу таблицу (глуповато конечно выглядить, но это так, для примера): Знакомство с Maven, Spring, MySQL, Hibernate и первое CRUD приложение (часть 4) - 2Ну думаю нет нужды подробно рассказывать о CSS, тут все довольно просто. На просторах интернета можно найти массу уже готовых вариантов оформления таблиц и форм. Но лучше конечно сделать оформление самостоятельно, тут не нужно быть дизайнером, это ж все-таки не Howой-то сложный сайт. Даже нескольких часов после первого знакомства хватит, чтобы сделать достаточно красивое и аккуратное оформление такой простой pages. К тому же в интернете полно всяких уроков, примеров, есть специальные сайты, где одновременно на одном экране можно редактировать HTML, CSS и сразу видеть How это все выглядит. Немного практики и можно творить настоящее искусство. Правда тут тоже не стоит сильно увлекаться (если конечно нет планов стать дизайнером), а то оформление это такая штука, тут можно застрять очень на долго. Я How первый раз начал разбираться с CSS то конкретно завис. Все хотел попробовать, каждое свойство, что-то крутил, ковырял, экспериментировал, брал pages Howих-нибудь сайтов и переделывал их до неузнаваемости. Я, наверное, неделю развлекался с этой игрушкой, больше ничего не делая, пока меня не отпустило :) Ну а так вообще конечно не стоит переусердствовать и делать непонятное пестрое чудо-юдо, нужно делать простенько и со вкусом. Единственное стоит отметить. Нужно понимать, что CSS — это описание оформления, а HTML — это разметка. Не стоит стараться абсолютно все сделать через CSS, некоторые моменты будет сделать очень сложно, а некоторые просто невозможно, когда в HTML это же делается парой лишних строк, а то и вовсе Howим-то одним атрибутом в теге. Нужно их комбинировать, всякие цвета, фоны, шрифты делать в CSS, а если например нужно объединить пару ячеек таблицы, проще использовать средства HTML. Ну вот к примеру что у меня получилось сделать со pageми за пару-тройку часов ковыряния с CSS и HTML (не буду тут уже расписывать, Howую кашу я наворотил чтобы этого добиться, в конце будет link на гитхаб этого проекта там можно будет посмотреть): Знакомство с Maven, Spring, MySQL, Hibernate и первое CRUD приложение (часть 4) - 3Не знаю конечно, насколько грамотно я там все сделал, но учитывая что я впервые увидел CSS за неделю до этого, думаю вполне годно получилось.

Разбиение на pages

Now все работает, выглядит вроде неплохо, но в таблице пока только несколько записей. А что, если в ней будет сотня фильмов, or тысяча, не очень удобно проматывать такой длиннющий список. Гораздо удобнее, когда список выводится pageми, штук по 10 записей, например. Поэтому сейчас и попробуем реализовать разбиение списка на pages (иногда это еще называют "пейджинг" or "пагинация" (англ. pagination)). Сделать это можно по-разному. Например, можно передавать полный список на jsp page и там уже формировать табличку на нужное кол-во записей. Или можно, допустим, в сервисе вытаскивать из общего списка нужные записи, а потом этот мини-список отправлять на jsp page для отображения. Но лучше всего конечно делать это на уровне базы данных. Идея в том, чтобы не брать из базы полный список и потом разбивать его на куски, а изначально доставать из базы нужный кусок, не трогая все остальное. Ведь зачем нам вытаскивать из базы все сотни or тысячи записей сразу, если нужная нам находится в первой десятке, лучше вытащим только одну эту десятку. Идем в DAO и добавим для метода allFilms параметр int page, который будет отвечать за номер pages (в сервисе, естественно, делаем то же самое). И немного изменим реализацию этого метода, если раньше мы вытаскивали весь список, то теперь будем вытаскивать только часть. С этим нам помогут методы setFirstResult (с Howой строчки таблицы начать) и setMaxResults (сколько записей вывести):
@SuppressWarnings("unchecked")
public List<Film> allFilms(int page) {
    Session session = sessionFactory.getCurrentSession();
    return session.createQuery("from Film").setFirstResult(10 * (page - 1)).setMaxResults(10).list();
}
Т.е. если это 1-я page, выводим максимум 10 записей, начиная с 0-ой, если это 5 page, то 10 записей начиная с 40-й (не забываем, что нумерация в базе начинается с 0). А еще дополнительно создадим метод, который будет возвращать количество записей в таблице. Нам это понадобится для того, чтобы знать число всех страниц и сформировать для них ссылки на нашей jsp странице:
public int filmsCount() {
     Session session = sessionFactory.getCurrentSession();
     return session.createQuery("select count(*) from Film", Number.class).getSingleResult().intValue();
 }
C помощью такого requestа мы получим количество всех записей в таблице (в виде int значения) не вытаскивая при этом сами записи. Теперь идем в контроллер и поработаем над методом, который возвращает главную page со списком фильмов:
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView allFilms(@RequestParam(defaultValue = "1") int page) {
    List&ltFilm> films = filmService.allFilms(page);
    int filmsCount = filmService.filmsCount();
    int pagesCount = (filmsCount + 9)/10;
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("films");
    modelAndView.addObject("page", page);
    modelAndView.addObject("filmsList", films);
    modelAndView.addObject("filmsCount", filmsCount);
    modelAndView.addObject("pagesCount", pagesCount);
    return modelAndView;
}
Здесь появилась новая annotation @RequestParam, которая указывает что данное meaning мы получаем из параметра requestа. Теперь, если мы перейдем по addressу с параметром, например http://localhost:8080/?page=4, то получим, соответственно, 4-ю page. Устанавливаем meaning по умолчанию "1", чтобы при запуске applications, когда мы переходим на address без параметра http://localhost:8080/, мы получали первую page. В методе мы получаем количество всех записей, потом таким вот нехитрым способом вычисляем количество страниц. Т.е. если у нас 10 записей, это 1 page, а если 11, то это уже 2. Ну и передаем в модель все это дело. Количество страниц нужно знать, чтобы сформировать для них всех ссылки в цикле, а количество фильмов пусть будет на всякий случай, если, например, захочется вывести эту информацию где-то на странице. Теперь осталось только зайти в films.jsp и добавить ссылки на каждую page с помощью вот такой конструкции:
<c:forEach begin="1" end="${pagesCount}" step="1" varStatus="i">
    <c:url value="/" var="url">
        <c:param name="page" value="${i.index}"/>
    </c:url>
    <a href="${url}">${i.index}</a>
</c:forEach>
Создаем ссылки по счетчику 1, 2, 3, ... и устанавливаем параметр по значению индекса.

Кстати таким же образом, How и с разбиением на pages, можно добавить и другие фишки, например сортировку, фильтрацию, поиск. Просто передаем в метод DAO различные параметры и формируем с их помощью соответствующий request к бд, чтобы вытянуть нужные записи, в нужном порядке.

Сделаем еще один маленький штрих. Возвращаемся в контроллер. В методах добавления, редактирования и удаления, после выполнения операции мы делаем перенаправление на главную page "redirect:/". Т.о. если мы будем где-нибудь на 50-й странице и нажмем редактировать запись, то после выполнения мы перейдем по addressу "/", т.е. вернемся на 1 page. Это не очень удобно, хотелось бы вернуться туда же, откуда и пришли. Решим это очень просто. Создадим в классе FilmController переменную экземпляра int page
private int page;
Внутри метода allFilms будем присваивать этой переменной meaning параметра page:
this.page = page;
Т.о. каждый раз, когда выполняется этот метод (т.е. когда мы перемещаемся по pageм), в переменную будет записываться meaning текущей pages. А затем мы используем это meaning в наших методах, чтобы перенаправить обратно на эту же page.
modelAndView.setViewName("redirect:/?page=" + this.page);

Заключение

На этом, пожалуй, и закончим. Получилось полноценное CRUD приложение. Оно конечно далеко от идеала (очень далеко), но его можно оптимизировать и доработать, исправить косяки и добавить функциональности. Можно использовать встроенные методы для crud операций; прикрутить фильтрацию, поиск, сортировку; добавить другие связанные таблицы; реализовать поддержку разных пользователей с авторизацией и аутентификацией и т.д. и т.п. Простор для фантазии безграничный, так что дерзайте. Ссылка на github этого проекта. Спасибо за внимание. P.S. Это моя первая в жизни попытка написать статью, так что не судите строго :). Прошу прощения, что не добавил всяких разных ссылок на полезные ресурсы, к сожалению, все ниHow не могу выработать привычку сохранять ссылки на источники, откуда черпаю информацию. Ну и, конечно же, извиняюсь за много букв, краткость не мой талант, надеюсь кто-нибудь сможет это осorть. Ссылки на все части
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION