Как стать автором
Обновить

Комментарии 33

У меня два вопроса.
Зачем gradle? Чтобы еще требовалось ставить groovy для сборки? :)
Второй вопрос касается mvc. Сейчас для добавления новых view и security каждый раз нужно добавлять код и пересобирать. Зачем?
«Чтобы еще требовалось ставить groovy для сборки? :)» в данном случае похоже на «Чтобы еще требовалось ставить maven(заменить на нужное — ant/bazel) для сборки»
groovy не требуется ставить для сборки, требуется запустить лишь ./gradlew build — он сам скачает бинарник gradle (а он в себе уже содержит все необходимое).
При этом скачиваться будет только один раз для всех проектов.
Впрочем, можно поставить и gradle в систему отдельно, но gradlew более гибко. Всегда знаешь, что собираешь нужной версией :)
Maven как правило из коробки есть практически везде. Ну это уже кадлый выбирает то что хочет. А что с mvc и security? Это как бы не очень хорошее решение.
Вопрос времени, может скоро gradle из коробки будет везде :) Хотя конечно вопрос «коробки». apt-get install gradle /apt-get install maven3 — разница не большая) Зато с ./gradlew точно знаешь что не нужно делать даже этого, просто запускай скрипт сборки, все само поставиться в случае отсутствия.
Про второй вопрос: я не автор статьи, но тут у всех подробности разные. Если автору не нужно пересобирать динамическое изменение security, то почему бы и нет? Gradle просто захотелось ответить.
Ага и mvc тоже? На каждый контроллер ходить вписывать. Зачем? Уже давно через через указание сканировать и аннотации controller можно это не вписывать.
1) Потому что у меня на работе он :) Думаю те, кто задаются таким вопросом, легко переделают Gradle конфиг в maven. Да и ставить ничего не нужно — все уже прилагается к проекту, а недостатющее оно дотянет само.
2) Ну это же не для CMS, изменение security редкое событие, а view обычно идут вместе с контроллером для которого созданы, статичных практически нету :)
а view обычно идут вместе с контроллером для которого созданы, статичных практически нету :)

Тогда зачем их такое количество плодить? Особенно если указать view можно прямо в контроллере, а сам контроллер можно объявить через аннотацию? Вот будет у меня десятка два контроллеров, это уже будет портянка.
1) посмотрите вторую часть, там вьюха из контроллера отдается :) или такой вариант тоже не устраивает?
2) не будет два десятка)) это же обучающий пример для новичков, а не полноценный проект
1) посмотрите вторую часть, там вьюха из контроллера отдается :) или такой вариант тоже не устраивает?

Уже давно можно делать return «add». Т.е. просто возвращать строку. Как у вас было принято делать в spring 2.5.

2) не будет два десятка)) это же обучающий пример для новичков, а не полноценный проект

Угу новички как раз и будут делать портянку. «В том учебном проекте было сделано именно так!» В примерах должны быть лучшие практики, а не худшие.
Уже давно можно делать return «add»

У меня вообще-то @RestController, а не Controller, в нем у всех методов по умолчанию @ResponseBody :)
Угу новички как раз и будут делать портянку. «В том учебном проекте было сделано именно так!» В примерах должны быть лучшие практики, а не худшие.

Ну у нас разные взгляды на то, что надо давать новичкам. Никто не мешает вам написать статью согласующуюся с вашим взглядом, или написать мне в лс что конкретно стоит поправить в моем.
У меня вообще-то @RestController, а не Controller, в нем у всех методов по умолчанию @ResponseBody :)

В add действии то?

    @RequestMapping(value = "/add",method = RequestMethod.GET)
    public String getUserForm()
    {
        return "add";
    }

Вернет просто строку add :) А не add.html
Вернет контроллер add.html. Настраивать надо уметь. Я это еще 5 лет назад делал.

habrahabr.ru/post/101546

Для tymleaf:

<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
                http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

        <!-- Configures support for @Controllers -->
        <mvc:annotation-driven conversion-service="conversionService"/>

        <mvc:resources mapping="/favicon.ico" location="/favicon.ico"/>
    <mvc:resources mapping="/img/**" location="/img/"/>
        <mvc:resources mapping="/js/**" location="/js/"/>
        <mvc:resources mapping="/css/**" location="/css/"/>
        <mvc:resources mapping="/fonts/**" location="/fonts/"/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="order" value="2"/>
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

        <bean class="org.thymeleaf.spring3.view.ThymeleafViewResolver">
                <property name="templateEngine" ref="templateEngine"/>
                <property name="characterEncoding" value="UTF-8"/>
                <property name="order" value="1"/>
        </bean>
</beans>

В том виде, в котором оно во второй части — не вернет :) А добавлять эти конфигурации в код я не хочу, на мой взгляд нельзя в таких статьях грузить тем, без чего можно обойтись.
Да и потом для контроллеров объявленных с аннотацией Controller оно и без этой кофигурации работает) Как раз стоит лишь вернуть строку. Это в 3 части будет
Для tymleaf насколько помню надо было крутить.
Добавьте в controllers такой класс:
ShowsViewController.java
package habraspring.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/showsview")
public class ShowsViewController {
    @RequestMapping(method = RequestMethod.GET)
    public String showView()
    {
        return "add";
    }
}


И откройте. Как видите, ничего настраивать не надо.
Вы уж определитесь вернет или нет.
Попробуйте быть внимательнее. Пятый раз уже одно и то же объясняю))
Если контроллер объявлен как
@RestController

как, например, Users контроллер, он просто так View возвращать не будет.
Но если он объявлен как
@Controller

то если вернуть строку он будет возвращать view с таким названием.
Эм. Теперь внимаааательно почитайте что я писал в начале. Я писал про Controller просто. И у вас там было
return new ModelView("add");


Причем тут RestController? А Thymeleaf насколько помню в обычном контроллере через возврат строки не подхватывался.
Потому что это RestContoller:
github.com/MaxPovver/ForHabrahabr/blob/withcontroller/src/main/java/habraspring/controllers/UsersController.java
Собственно только поэтому я и не возвращал там просто «add»
(шестой раз)
А Thymeleaf насколько помню в обычном контроллере через возврат строки не подхватывался.

В текущей версии — подхватывается.
Потому что это RestContoller

Тфу ты. Но вообще надо отделять тогда в отдельный контроллер. Опять же во избежание.

В текущей версии — подхватывается.

Значит меньше писанины.
Я напишу несколько замечаний/дополнений которые могут быть полезны юзерам:
1. Вместо *.properties можно использовать *.yml — меньше текста, проще читать.
2. Я бы не советовал использовать Thymeleaf, он довольно медленный и у него КРАЙНЕ неудобный синтаксис для шаблонизатора.
3. Приложение можно запустить не только с помощью плагина Gradle но и из класса Application.
4. Gradle для нас оказался сыроват, мы используем менее гибкий но более стабильный Maven.
5. Spring boot умеет обновлять вашу схему в БД с помощью Hibernate. Свойство в application.properties, spring.jpa.hibernate.ddl-auto.
6. Я бы не советовал использовать Spring Data JPA. Ваш код 100% может обойтись без этого модуля, лучше возьмите QueryDSL и напишите всю прослойку Repository самостоятельно. Иначе в определенный момент вы получите кашу из методов-запросов, запросов Query, нативных запросов в SQL или с помощью JPA Criteria API. Если вы все таки решили использовать Spring Data JPA, то не поленитесь посмотреть исходники там есть интересные штуки типо AbstractPersistable.
>Я бы не советовал использовать Thymeleaf, он довольно медленный

довольно медленный — это сколько в попугаях? что именно медленное?

>Иначе в определенный момент вы получите кашу из методов-запросов, запросов Query, нативных запросов в SQL или с помощью JPA Criteria API

собсно, спринг-дата для того и создан, чтобы забыть про criteria api
никаких проблем в смешении методов-запросов и Query не вижу.
нативных запросов вообще должен быть крайний минимум, или зачем там вообще хибер появился? по крайней мере, нативных запросов будет не больше, чем без спринг-даты )
Ниже есть бенчмарк, типа весьма тормоз :)
2. Я бы не советовал использовать Thymeleaf, он довольно медленный и у него КРАЙНЕ неудобный синтаксис для шаблонизатора.

Предложите другой вариант, который хорошо интегрируется с Spring MVC быстрый и у которого удобный синтаксис. JSTL не предлагать :)

Я бы не советовал использовать Spring Data JPA. Ваш код 100% может обойтись без этого модуля, лучше возьмите QueryDSL и напишите всю прослойку Repository самостоятельно. Иначе в определенный момент вы получите кашу из методов-запросов, запросов Query, нативных запросов в SQL или с помощью JPA Criteria API.

Я посмотрел QueryDSL выглядит не очень. Опять же делать свой репозиторий это возврат к временам до Spring Data. И да с чего у вас каша будет? Вот определен у вас интерфейсы ваших репозиториев, ну размещайте туда все вызовы через аннотации. Ну все же можно. В итоге кода получается меньше и каши меньше.

> Предложите другой вариант, который хорошо интегрируется с Spring MVC быстрый и у которого удобный синтаксис. JSTL не предлагать :)

Варианты есть: jtwig.org, www.mitchellbosecke.com/pebble/home, github.com/greenlaw110/Rythm, github.com/jreijn/spring-comparing-template-engines.

Мы используем Pebble engine.

> Я посмотрел QueryDSL выглядит не очень. Опять же делать свой репозиторий это возврат к временам до Spring Data. И да с чего у вас каша будет? Вот определен у вас интерфейсы ваших репозиториев, ну размещайте туда все вызовы через аннотации. Ну все же можно. В итоге кода получается меньше и каши меньше.

Это возможно дело вкуса. Я попробую описать причины по которым сейчас я не вижу смысла в Spring Data JPA.

1. Короткие методы — не нужны, да первые ощущения от findAll положительные, но со временем понимаешь что тут у тебя метод findAll а вот тут Query, а там еще Specifications. А нужно чтобы все выглядело одинаково(или хочется).
2. Query не гибкий метод потому что иногда нужны динамические запросы. По итогу используем Criteria API, потому что Specifications нам явно не хватает.

В результате я смотрю на Spring Data JPA и думаю, а зачем мне весь этот сахар если он покрывается стандартным JPA полностью, а плюсов никаких не дает. Только каша из разных способов сделать одно и то же.

С другой стороны JPA мне тоже не хватает, потому что у него не все хорошо с нативными запросами, с джоинами по несвязанным таблицам и выборкой отдельных полей. В результате мы стали использовать QueryDSL который позволяет делать типобезопасные, универсальные запросы к JDBC,JPA и collections.
Варианты есть: jtwig.org, www.mitchellbosecke.com/pebble/home, github.com/greenlaw110/Rythm, github.com/jreijn/spring-comparing-template-engines.

Мы используем Pebble engine.

Посмотрю. Вот только у Pebble не понятно как сделана интеграция форм в spring.

1. Короткие методы — не нужны, да первые ощущения от findAll положительные, но со временем понимаешь что тут у тебя метод findAll а вот тут Query, а там еще Specifications. А нужно чтобы все выглядело одинаково(или хочется).

Если начинается что-то сложнее в него добавить сортировку, переделываем на метод

2. Query не гибкий метод потому что иногда нужны динамические запросы. По итогу используем Criteria API, потому что Specifications нам явно не хватает.

Не совсем понял. Не хватает подстановки запросов?

В результате я смотрю на Spring Data JPA и думаю, а зачем мне весь этот сахар если он покрывается стандартным JPA полностью, а плюсов никаких не дает.

Вполне дает. Не надо писать свою реализацию репозитория, не требуется писать на каждый DAO свою реализацию, интерфейсов вполне хватает. Весьма часто можно просто использовать его DSL для получения необходимого результата.
> Не совсем понял. Не хватает подстановки запросов?

Не хватает динамики в запросах.
В одном случае мне нужен такой запрос:
Query(«SELECT u FROM User u JOIN FETCH u.profile»)
В другом случае:
Query(«SELECT u FROM User u»)
А в третьем:
Query(«SELECT u FROM User u JOIN FETCH u.profile JOIN FETCH u.role»)

А к этому мне иногда еще нужна постраничная разбивка с сортировкой, иногда просто сортировка.

У меня тут два варианта решения проблемы:
1. Написать три разных метода и сверху каждого сделать аннотации Query.
2. Сделать один метод в котором динамически строить запрос на основе входных параметров(нужно ли вытаскивать профиль или нет, нужна ли роль или нет).

Второй вариант для меня предпочтительней потому что в рантайме я могу изменить запросы. Поэтому что бы так сделать мне приходится отдельно писать метод и в нем с помощью QueryDSL описывать логику выборки данных.
Обычно такое делают вообще через ORM. Ну тут уже каждый страдает как ему кажется удобным.
по умолчанию вторичные сущности грузятся лениво в момент когда были запрошены :)
Я понимаю как работает меппинг в Hibernate, только в данном случае мне нужно за один запрос вытащить всех юзеров с их профилями(сразу) а не делать дополнительно кучу LAZY запросов.
Ну да, аннотации в таком плане не помощник, ими ленивость можно только в положение вкл/выкл ставить
Для этого или можно прописать тянуть все сразу ну или вешать хинты. Сильно зависит от ситуации.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.