• Как правильно разрастаться веб приложению написанному на spring?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Сложные фильтры должны применяться, по возможности, в запросах к хранилищу данных.
    Если нет такой возможности, то их желательно в DAO и помещать.

    А вообще - нет никакого смысла делать из этого проблему и уж тем более пытаться её решить. Код работает, выполняет свою задачу и не мешает разработчику - значит, трогать его не надо. Это пустая трата времени, особенно, когда проект в процессе разработки. Вот когда проект реализован и корректно выполняет все свои задачи, тогда и стоит задуматься о рефакторинге.

    spoiler
    8nm64g.jpg
    Ответ написан
    Комментировать
  • Сколько нужно иметь оперативки на ноутбуке для работы с IDEA Java?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Для начала нужно определиться, разработку каких проектов планируется вести, и какое окружение требуется для разработки и тестирования. По своему опыту могу сказать, что 8Гб - достаточный минимум (даже без SSD) для разработки. Во всяком случае при работе с Linux Mint я не замечал проблем при одноразовом запуске 4-5 разрабатываемых enterprise-проектов с запущенными IDE (будь то NetBeans или IDEA), Java Mission Control и браузером.
    Браузер, кстати, не будет жрать много ресурсов, если не открывать по несколько десятков вкладок.

    И да, SSD является очень желательным приобретением, действительно ускоряет работу в IDE.

    Ноутбук Clevo W370ET, процессор i7-3610QM и 8Gb RAM
    Ответ написан
  • Насколько будет оптимально использование такого способа?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    • Используй ORM или хотя бы Spring JDBC, чтобы не городить костыли вокруг работы с соединениями, преобразований типов и т.д.
    • Учись проверять работоспособность кода модульными и интеграционными тестами. Ты же знаешь, что должен сделать код, значит и тесты сможешь написать.
    • Не надо:
      try
              {
                  Class.forName(ClassDriverName);
              } catch (ClassNotFoundException e)
              {
                  throw new RuntimeException(e.getMessage());
              }

    • Тоже не надо, т.к. conn у тебя в try-with-resources.
      conn.close();

    • Три вложенных while с переопределением существующих переменных.
      9764489.jpg


    Этот код неоптимален. Ни разу.
    Ответ написан
    Комментировать
  • Как передать json объект как get параметр?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Во-первых нужно сериализовать передаваемые данные при помощи URLEncode.
    Во-вторых нужен будет конвертер, способный превратить строку в HashMap.

    а вообще, как сказал i_visseri, если требуется передать какую-то полезную нагрузку, лучше использовать POST-запросы.
    Ответ написан
  • Как правильно организовать валидацию данных?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Для начала прочти документацию по Spring. Всё максимально разжёвано.

    1. Дополнительные классы-валидаторы потребуются только для особенных случаев. В целом можно ограничиться аннотациями из Java Bean Validation и его реализаций.
    2. Вообще-то в BindingResult собираются результаты валидации. И ошибки валидации, которые ты отправишь потом на фронт, берутся из него же.
    3. В смысле? Тебе лень в конце каждого метода написать return ResponseEntity.ok()?
    Ответ написан
    Комментировать
  • Как увеличить продолжительность сесси в Spring Security?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Если ты разворачиваешь приложение в сервлет-контейнере, то в web.xml нужно дополнительно указать время жизни сессии:
    <session-config>
            <session-timeout>60</session-timeout>
    </session-config>


    Пример для 60 минут, если нужна бесконечная сессия, то -1
    Ответ написан
    Комментировать
  • Почему возникает ошибка при сохранении?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Нужно добавить каскадирование при сохранении:
    @Basic(optional = false)
    @OneToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "sub_model_id")
    public MySubModel subModel;
    Ответ написан
    1 комментарий
  • Как подключить SphinxQl в Spring?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Скорее всего проблема в несовместимости jdbc-драйвера MySQL и сервера MySQL.
    Ответ написан
  • Где набраться опыта Java и каковы основные тренды на Java?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Самые прибыльные направления в жабе - энтерпрайз. В нём два основных тесно связанных направления: Java EE и Spring. Сейчас очень актуально, особенно на западе, всё, связанное с облачными сервисами, соответственно, смотреть рекомендую в сторону Spring Cloud. Одно "но" - порог вхождения может показаться очень высоким.
    Ответ написан
  • Как сделать страницу авторизации?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    В конфигурации нужно включить форм-авторизацию:
    @Configuration
        public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http
                    //твои
                    //настройки
                    .formLogin();
            }
        }
    Ответ написан
    Комментировать
  • Как сделать валидацию данных?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Я на практике использую следующий подход: для каждой хранимой сущности, которую может создать/изменить пользователь, я создаю класс, описывающий форму (иногда бывает, что для редактирования и создания используются даже разные классы в виду разного набора полей).
    Это делается по двум причинам: во-первых - не все поля в хранимой сущности пользователи могут создавать/изменять (например, даты создания/редактирования и идентификаторы), во-вторых - вынесение аннотаций валидации из класса сущности.

    Теперь ближе к делу: для валидации существуют аннотации из пакета javax.validation.constraints, а также дополнительные, предоставляемые реализациями Bean Validation API (например @Email из Hibernate Validator).

    Допустим, у нас есть класс, представляющий собой форму регистрации:
    SignUpForm.java
    public class SignUpForm {
        @Email
        private String email;
    
        @Size(min = 8)
        @Pattern(regexp = "какая-нибудь регулярка для проверки надёжности пароля")
        private String password;
    }


    В контроллере мы будем принимать форму таким образом:
    SignUpController.java
    public class SignUpController {
        public ResponseEntity signUp(@RequestBody @Valid SignUpForm form, BindingResult bindingResult) {
        }
    }



    В form будут содержаться данные, отправленные пользователем, а в bindingResult - результат валидации, который можно легко проверить, вызвав bindingResult.hasErrors(). Отмечу только то, что аргумент класса BindingResult должен быть сразу после аргумента, помеченного аннотациями @RequestBody и valid, в других случаях валидация работать не будет.

    Но дальше - больше. Допустим, нам нужно добавить поле для подтверждения пароля и проверять его соответствие паролю. В таком случае нам надо добавить свою аннотацию (в данном случае на класс) и валидатор.
    Новый класс формы:
    SignUpForm.java
    @PasswordMatch
    public class SignUpForm {
        @Email
        private String email;
    
        @Size(min = 8)
        @Pattern(regexp = "какая-нибудь регулярка для проверки надёжности пароля")
        private String password;
    
        private String passwordConfirmation;
    }


    Аннотация:
    PasswordMatch.java
    @Target({TYPE, ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Constraint(validatedBy = PasswordMatchValidator.class)
    @Documented
    public @interface PasswordMatch {
    
        String message() default "{constraints.passwordmatch}";
    
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    
        @Target({TYPE, ANNOTATION_TYPE})
        @Retention(RUNTIME)
        @Documented
        @interface List {
    
            PasswordMatch[] value();
        }
    }


    Ну и валидатор:
    PasswordMatchValidator.java
    public class PasswordMatchValidator implements ConstraintValidator<PasswordMatch, SignUpForm> {
    
        @Override
        public void initialize(PasswordMatch constraintAnnotation) {
        }
    
        @Override
        public boolean isValid(SignUpForm value, ConstraintValidatorContext context) {
                return Objects.equals(value.getPassword(), value.getPasswordConfirmation());
        }
    }


    И ещё один способ валидации - при помощи спринговых валидаторов. Допустим, нам нужно проверить существование указанного email в нашей БД, что вполне вписывается в процесс валидации. В таком случае пишем валидатор:
    SignUpFormValidator.java
    public class SignUpFormValidator implements Validator {
        public boolean supports(Class<?> type) {
            return SignUpForm.class.isAssignableFrom(type);
        }
        public void validate(Object target, Errors errors) {
            SignUpForm form = (SignUpForm) target;
            // проверяем, что нужно и добавляем ошибки в errors, если они есть
        }
    }


    Регистрируем его в контроллере:
    SignUpController.java
    public class SignupController {
        @InitBinder
        public void initBinder(WebDataBinder binder) {
            binder.addValidators(new SignUpFormValidator());
        }
    }


    После этого Spring будет производить дополнительную валидацию при помощи этого валидатора.

    Более подробно с валидацией в Spring можно почитать в официальной документации.
    Ответ написан
    Комментировать
  • Как организовать правильный маппинг объектов в спринге?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Если в рамках WebMVC, то из контроллера во вьюхи можно и DTO передавать. В обратную сторону (т.е. от клиента при отправке формы) - лучше иметь отдельные классы, представляющие собой набор полей форм (с точки зрения валидации удобнее).
    Если в рамках REST, то есть такой зверь как HATEOAS.
    Ответ написан
    Комментировать
  • Где хранить данные для авторизации?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Сами данные авторизации лучше хранить в файле конфигурации. Оттуда они должны доставаться контекстом приложения и подставляться в свойства класса-клиента API. Как-то так.
    Ответ написан
    Комментировать
  • В каких случаях может потребоваться JNDI?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    JNDI можно использовать для доступа к общим ресурсам, вроде соединений с БД, очередей сообщений, конфигурационных переменных. К примеру, можно в настройках сервера приложений создать соединение с БД, которое будет использоваться несколькими приложениями.
    Однако, сейчас JNDI становится менее популярным инструментом, так как современные приложения разворачиваются в большинстве случае не в серверах приложений. Для распределённой конфигурации сейчас есть такие инструменты, как Spring Cloud Config, Apache Zookeeper, Consul и прочие.
    Ответ написан
    Комментировать
  • Spring: Как сделать аутентификацию на основе bearer токена?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    1. Класс, реализующий Authentication.
      TokenAuthentication.java
      public class TokenAuthentication extends AbstractAuthenticationToken {
          private final Object principal;
          private final Object credentials;
          public TokenAuthentication(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
              super(authorities);
              this.principal = principal;
              this.credentials = credentials;
              this.setAuthenticated(true);
          }
          public TokenAuthentication(Object principal, Object credentials) {
              this(principal, credentials, null);
          }
          @Override
          public Object getPrincipal() {
              return principal;
          }
          @Override
          public Object getCredentials() {
              return credentials;
          }
      }

    2. Фильтр, с которого начнётся процесс аутентификации пользователя. Фильтр должен создать объект типа Authentication и попробовать аутентифицировать его при помощи AuthenticationManager.
      TokenHeaderAuthenticationFilter.java
      public class TokenHeaderAuthenticationFilter extends OncePerRequestFilter {
      
          private final AuthenticationManager authenticationManager;
      
          public TokenHeaderAuthenticationFilter(AuthenticationManager authenticationManager) {
              this.authenticationManager = authenticationManager;
          }
      
          @Override
          protected void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
              if (SecurityContextHolder.getContext().getAuthentication() != null && SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) {
                  filterChain.doFilter(servletRequest, servletResponse);
                  return;
              }
              String headerValue = servletRequest.getHeader("X-Authorization");
              if (StringUtils.isEmpty(headerValue)) {
                  filterChain.doFilter(servletRequest, servletResponse);
                  return;
              }
              String token = headerValue.split("\\s")[1];// ну или headerValue.replace("Bearer ")
              TokenAuthentication authenticationToken = new TokenAuthentication(null, token);
              authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(servletRequest));
      
              Authentication authenticationResult = authenticationManager.authenticate(authenticationToken);
              SecurityContextHolder.getContext().setAuthentication(authenticationResult);
              filterChain.doFilter(servletRequest, servletResponse);
          }
      }

    3. Класс, реализующий AuthenticationProvider. Этот класс и будет производить аутентификацию полученных данных.
      TokenAuthenticationProvider.java
      public class TokenAuthenticationProvider implements AuthenticationProvider {
          @Override
          public boolean supports(Class<?> authentication) {
              return TokenAuthentication.class.isAssignableFrom(authentication);
          }
          @Override
          public Authentication authenticate(Authentication authentication) throws AuthenticationException {
              // здесь должна быть реализована логика аутентификации полученных данных
          }
      }

    4. Последний штрих - конфигурация.
      SecurityConfig.java
      @Configuration
      public class SecurityConfig extends WebSecurityConfigurerAdapter {
      
          @Bean
          public AuthenticationProvider tokenAuthenticationProvider() {
              return new TokenAuthenticationProvider();
          }
      
          @Override
          protected void configure(HttpSecurity http) throws Exception {
              http.addFilterAfter(new TokenHeaderAuthenticationFilter(authenticationManagerBean()), BasicAuthenticationFilter.class)
                      .authenticationProvider(tokenAuthenticationProvider())
                      .authorizeRequests()
                      .anyRequest().authenticated();
          }
      }

    Ответ написан
    Комментировать
  • Java EE умер, есть ли смысл делать на нем проекты?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Стоит ли сейчас разрабатывать web-проекты с использованием Java EE

    Вполне себе стоит, если душа не лежит к Spring или не позволяет корпоративная этика

    насколько я понял его пустили в свободное плавание на github

    Такое себе "свободное" плавание. ИМХО, выход из-под крыла Oracle только в плюс пойдёт.

    Насколько зависим Spring от Java EE ?

    Spring Web зависит от Servlet API, может использовать в качестве отображений JSP, а также интегрирован с JSF. Spring Data JPA, как видно из названия, основан на JPA. Есть возможность использования JMS. И т.д. в целом, т.е. Spring очень тесно связан с Java EE
    Ответ написан
    2 комментария
  • Unity3D server. Node.js или Java?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Зная возможности и ноды и жабы, выбрал бы Java с использованием Netty, во всяком случае на нём очень серьёзный сетевой хайлоад пишется.
    Ответ написан
    Комментировать
  • По каким материалам изучать Java EE?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Если именно Java EE, то рекомендую книгу Изучаем Java EE 7 (Э. Горнсалвес), написана книга хорошо, перевод вполне сносный. Если хочется чего-то из мира Java EE, то рекомендую Spring и его официальную документацию, которая ничем не хуже книг.
    Ответ написан
    Комментировать
  • Как соотносится сложность написания веб-проектов на asp.net c JavaEE/spring?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Про ASP.net ничего не скажу, но свои пять копеек про JavaEE/Spring вставлю. ИМХО, Java EE имеет порог вхождения выше, чем Spring (особенно мне это так казалось, когда я начинал изучать и то и другое одновременно - Spring 2 и Java EE 5, может, что-то и изменилось за прошедшее время). Spring в чистом виде для абсолютного новичка в Java - тоже не подарок, хотя документация очень хорошая (и я её считаю чуть ли не эталонной). Для полноценного Java EE потребуется сервер приложений аля Glassfish, JBoss, Wildfly и т.д, тогда как веб-приложению на Java EE или Spring нужен только сервлет-контейнер (Tomcat, Jetty или Undertow). Но для Spring Boot поднимать вообще ничего не надо, достаточно только нормальной IDE (NetBeans, IDEA, Eclipse) и всё. Spring Boot идеален для начала изучения Spring, но это не исключает необходимости в более подробном изучении Spring Framework, Security, Data и т.д. в дальнейшем.

    CORE, SE

    одно и то же

    JavaEE - это платформа минимум для небольшой команды разработчиков, и в одного на ней что-то поднимать долго.

    Всё приходит с опытом, но самостоятельно вполне можно разрабатывать проекты.
    Ответ написан
    Комментировать
  • Spring Boot + Html5 video. Как показывать видео, которые расположены в другой директории системы?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Конфигурацией:
    @Configuration
    public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/video/**").addResourceLocations("/path/to/video");
        }
    }


    Таким образом по адресу localhost:8080/video/kotiki.mp4 будет доступно видео /path/to/video/kotiki.mp4 на файловой системе (пример для *nix)
    Ответ написан
    Комментировать