Spring MVC Интервью Вопросы

Spring MVC Интервью Вопросы

1. Вступление

Spring MVC - это оригинальный веб-фреймворк от Spring, основанный на Servlet API. Он предоставляет архитектуру Model-View-Controller, которую можно использовать для разработки гибких веб-приложений.

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

Для получения дополнительных вопросов по Spring Framework вы можете проверитьanother Spring related article из нашегоinterview questions series.

2. Основные Spring MVC Вопросы

Q1. Почему мы должны использовать Spring MVC?

Spring MVC implements a clear separation of concerns that allows us to develop and unit test our applications easily.

Понятия как:

  • Диспетчер Сервлет

  • Контроллеры

  • Просмотр резольверов

  • Представления, Модели

  • ModelAndView

  • Атрибуты модели и сеанса

полностью независимы друг от друга, и они ответственны только за одну вещь.

Следовательно,MVC gives us quite big flexibility. Он основан на интерфейсах (с предоставленными классами реализации), и мы можем настроить каждую часть инфраструктуры, используя настраиваемые интерфейсы.

Another important thing is that we aren’t tied to a specific view technology (for example, JSP), but we have the option to choose from the ones we like the most.

Такжеwe don’t use Spring MVC only in web applications development but in the creation of RESTful web services as well.

Q2. Какова роль аннотации@Autowired?

The @Autowired annotation can be used with fields or methods for injecting a bean by type. Эта аннотация позволяет Spring разрешать и вводить взаимодействующие bean-компоненты в ваш bean-компонент.

Для получения дополнительной информации, пожалуйста, обратитесь к руководству о@Autowired in Spring.

Q3. Объяснить модель атрибута

Аннотация@ModelAttribute - одна из самых важных аннотаций в Spring MVC. It binds a method parameter or a method return value to a named model attribute and then exposes it to a web view.

Если мы используем его на уровне метода, это означает, что целью этого метода является добавление одного или нескольких атрибутов модели.

С другой стороны, при использовании в качестве аргумента метода он указывает, что аргумент должен быть получен из модели. Если нет, мы должны сначала создать его экземпляр, а затем добавить его в модель. При наличии в модели мы должны заполнить поля аргументов из всех параметров запроса, имеющих совпадающие имена.

Подробнее об этой аннотации можно найти в нашемarticle related to the @ModelAttribute annotation.

Q4. Объясните разницу между@Controller и@RestController?

Основное различие между аннотациями@Controller и@RestController заключается в том, чтоthe @ResponseBody annotation is automatically included in the @RestController. Это означает, что нам не нужно аннотировать наши методы-обработчики с помощью@ResponseBody. Нам нужно сделать это в классе@Controller, если мы хотим записать тип ответа непосредственно в тело ответа HTTP.

Q5. Опишите aPathVariable

We can use the @PathVariable annotation as a handler method parameter in order to extract the value of a URI template variable.

Например, если мы хотим получить пользователя по идентификатору изwww.mysite.com/user/123, мы должны отобразить наш метод в контроллере как/user/{id}:

@RequestMapping("/user/{id}")
public String handleRequest(@PathVariable("id") String userId, Model map) {}

The @PathVariable has only one element named value. It’s optional and we use it to define the URI template variable name. Если мы опускаем элемент значения, тогда имя переменной шаблона URI должно совпадать с именем параметра метода.

Также разрешено иметь несколько аннотаций@PathVariable, объявив их одну за другой:

@RequestMapping("/user/{userId}/name/{userName}")
public String handleRequest(@PathVariable String userId,
  @PathVariable String userName, Model map) {}

или поместив их все вMap<String, String> илиMultiValueMap<String, String>:

@RequestMapping("/user/{userId}/name/{userName}")
public String handleRequest(@PathVariable Map varsMap, Model map) {}

Q6. Проверка с использованием Spring MVC

Spring MVC supports JSR-303 specifications by default. We need to add JSR-303 and its implementation dependencies to our Spring MVC application. Например, Hibernate Validator - это одна из реализаций JSR-303, которая находится в нашем распоряжении.

JSR-303 - это спецификация Java API для проверки bean-компонентов, часть JavaEE и JavaSE, которая обеспечивает соответствие свойств bean-компонента определенным критериям, используя такие аннотации, как@NotNull,@Min и@Maxс. Подробнее о валидации читайте в статьеJava Bean Validation Basics.

Spring offers the @Validator annotation and the BindingResult class. РеализацияValidator вызовет ошибки в методе обработчика запросов контроллера, когда у нас есть недопустимые данные. Затем мы можем использовать классBindingResult, чтобы получить эти ошибки.

Помимо использования существующих реализаций, мы можем сделать и свои. Для этого мы сначала создаем аннотацию, которая соответствует спецификациям JSR-303. Затем мы реализуем классValidator. Другой способ - реализовать интерфейс SpringValidator и установить его в качестве валидатора с помощью аннотации@InitBinder в классеController.

Чтобы узнать, как реализовать и использовать свои собственные проверки, см. Руководство поCustom Validation in Spring MVC.

Q7. Что такое@RequestBody и@ResponseBody?

The @RequestBody annotation, used as a handler method parameter, binds the HTTP Request body to a transfer or a domain object. Spring автоматически десериализует входящий HTTP-запрос к объекту Java с помощью Http Message Converter.

When we use the @ResponseBody annotation on a handler method in the Spring MVC controller, it indicates that we’ll write the return type of the method directly to the HTTP response body. Мы не будем помещать его вModel, и Spring не будет интерпретировать его как имя представления.

Пожалуйста, ознакомьтесь со статьей о@RequestBody and @ResponseBody, чтобы узнать больше об этих аннотациях.

Q8. ОбъяснитеModel,ModelMap иModelAndView?

The Model interface defines a holder for model attributes. The ModelMap has a similar purpose, with the ability to pass a collection of values. Затем он обрабатывает эти значения, как если бы они находились в пределахMap. Следует отметить, что вModel (ModelMap) мы можем хранить только данные. Мы помещаем данные и возвращаем имя представления.

С другой стороны,with the ModelAndView, we return the object itself. Мы устанавливаем всю необходимую информацию, такую ​​как данные и название представления, в возвращаемом объекте.

Вы можете найти более подробную информацию в статье оModel, ModelMap, and ModelView.

Q9. ОбъяснитеSessionAttributes иSessionAttribute

The @SessionAttributes annotation is used for storing the model attribute in the user’s session. Мы используем его на уровне класса контроллера, как показано в нашей статье оSession Attributes in Spring MVC:

@Controller
@RequestMapping("/sessionattributes")
@SessionAttributes("todos")
public class TodoControllerWithSessionAttributes {

    @GetMapping("/form")
    public String showForm(Model model,
      @ModelAttribute("todos") TodoList todos) {
        // method body
        return "sessionattributesform";
    }

    // other methods
}

В предыдущем примере атрибут модели «todos» будет добавлен к сеансу, если@ModelAttribute и@SessionAttributes имеют одинаковый атрибут имени.

If we want to retrieve the existing attribute from a session that is managed globally, we’ll use @SessionAttribute annotation as a method parameter:

@GetMapping
public String getTodos(@SessionAttribute("todos") TodoList todos) {
    // method body
    return "todoView";
}

Q10. Какова цель@EnableWebMVC?

The @EnableWebMvc annotation’s purpose is to enable Spring MVC via Java configuration. Это эквивалент<mvc: annotation-driven> в конфигурации XML. Эта аннотация импортирует конфигурацию Spring MVC изWebMvcConfigurationSupport. Он включает поддержку аннотированных классов@Controller, которые используют@RequestMapping для сопоставления входящих запросов с методом обработчика.

Вы можете узнать больше об этой и подобных аннотациях в нашихGuide to the Spring @Enable Annotations.

Q11. Что такоеViewResolver весной?

The ViewResolver enables an application to render models in the browser - без привязки реализации к конкретной технологии просмотра -by mapping view names to actual views.

Чтобы узнать больше оViewResolver, взгляните на нашGuide to the ViewResolver in Spring MVC.

Q12. Что такоеBindingResult?

BindingResult is an interface from org.springframework.validation package that represents binding results. We can use it to detect and report errors in the submitted form. Его легко вызвать - нам просто нужно убедиться, что мы поместили его в качестве параметра сразу после проверяемого объекта формы. Необязательный параметрModel должен стоять послеBindingResult, как это видно вcustom validator tutorial:

@PostMapping("/user")
public String submitForm(@Valid NewUserForm newUserForm,
  BindingResult result, Model model) {
    if (result.hasErrors()) {
        return "userHome";
    }
    model.addAttribute("message", "Valid form");
    return "userHome";
}

When Spring sees the @Valid annotation, it’ll first try to find the validator for the object being validated. Затем он подберет аннотации проверки и вызовет валидатор. Наконец, найденные ошибки будут помещены вBindingResult и добавлены к модели представления.

Q13. Что такое объект поддержки формы?

The form backing object or a Command Object is just a POJO that collects data from the form we’re submitting.

Следует помнить, что в нем нет никакой логики, только данные.

Чтобы узнать, как использовать объект поддержки формы с формами в Spring MVC, ознакомьтесь с нашей статьей оForms in Spring MVC.

Q14. Какова роль аннотации@Qualifier?

It is used simultaneously with the @Autowired annotation to avoid confusion when multiple instances of a bean type are present.

Давайте посмотрим на пример. Мы объявили два одинаковых bean-компонента в XML-конфигурации:


    


    

Когда мы пытаемся подключить bean-компонент, мы получимorg.springframework.beans.factory.NoSuchBeanDefinitionException.. Чтобы исправить это, нам нужно использовать@Qualifier, чтобы сообщить Spring о том, какой bean-компонент должен быть подключен:

@Autowired
@Qualifier("person1")
private Person person;

Q15. Какова роль аннотации@Required?

Аннотация@Required используется в методах установки и указывает, что свойство bean-компонента, имеющее эту аннотацию, должно быть заполнено во время конфигурации. В противном случае контейнер Spring выдаст исключениеBeanInitializationException.

Кроме того,@Required отличается от@Autowired, поскольку он ограничен сеттером, а@Autowired - нет. @Autowired также можно использовать для связи с конструктором и полем, в то время как@Required только проверяет, установлено ли свойство.

Давайте посмотрим на пример:

public class Person {
    private String name;

    @Required
    public void setName(String name) {
        this.name = name;
    }
}

Теперьname bean-компонентаPerson необходимо установить в конфигурации XML следующим образом:


    

Обратите внимание, что@Required doesn’t work with Java based @Configuration classes by default. Если вам нужно убедиться, что все ваши свойства установлены, вы можете сделать это при создании bean-компонента в аннотированных методах@Bean.

Q16. Опишите шаблон переднего контроллера

In the Front Controller pattern, all requests will first go to the front controller instead of the servlet. It’ll make sure that the responses are ready and will send them back to the browser. This way we have one place where we control everything that comes from the outside world.

Фронт-контроллер идентифицирует сервлет, который должен обработать запрос первым. Затем, когда он получит данные обратно от сервлета, он решит, какое представление визуализировать, и, наконец, он отправит обработанное представление обратно в качестве ответа:

image

Чтобы увидеть детали реализации, ознакомьтесь с нашимGuide to the Front Controller Pattern in Java.

Q17. Что такое архитектуры Model 1 и Model 2?

Модель 1 и Модель 2 представляют две часто используемые модели проектирования, когда речь идет о разработке веб-приложений Java.

In Model 1, a request comes to a servlet or JSP where it gets handled. Сервлет или JSP обрабатывает запрос, обрабатывает бизнес-логику, извлекает и проверяет данные и генерирует ответ:

image

Поскольку эту архитектуру легко реализовать, мы обычно используем ее в небольших и простых приложениях.

С другой стороны, это неудобно для крупномасштабных веб-приложений. Функциональные возможности часто дублируются в JSP, где бизнес-логика и логика представления взаимосвязаны.

Модель 2 основана на шаблоне проектирования контроллера представления модели и отделяет представление от логики, которая управляет содержимым.

Furthermore, we can distinguish three modules in the MVC pattern: the model, the view, and the controller. Модель представляет динамическую структуру данных приложения. Он отвечает за манипулирование данными и бизнес-логикой. Представление отвечает за отображение данных, в то время как контроллер служит интерфейсом между двумя предыдущими.

В модели 2 запрос передается контроллеру, который обрабатывает требуемую логику, чтобы получить правильный контент, который должен отображаться. Затем контроллер помещает содержимое обратно в запрос, обычно в виде JavaBean или POJO. Он также решает, какое представление должно отображать содержимое, и, наконец, передает ему запрос. Затем представление отображает данные:

image

3. Advanced Spring MVC Вопросы

Q18. В чем разница между аннотациями@Controller,@Component,@Repository, и@Service весной?

Согласно официальной документации Spring,@Component - это общий стереотип для любого компонента, управляемого Spring. @Repository,@Service и@Controller являются специализациями@Component для более конкретных случаев использования, например, на уровнях сохраняемости, обслуживания и представления, соответственно.

Давайте посмотрим на конкретные варианты использования последних трех:

  • @Controller - указывает, что класс выполняет роль контроллера и обнаруживает аннотации@RequestMapping внутри класса

  • @Service - указывает, что класс содержит бизнес-логику и вызывает методы на уровне репозитория

  • @Repository - указывает, что класс определяет репозиторий данных; его задача - перехватывать специфичные для платформы исключения и повторно генерировать их как одно из унифицированных непроверяемых исключений Spring.

Q19. Что такоеDispatcherServlet иContextLoaderListener?

Проще говоря, в шаблоне проектирования Front Controller один контроллер отвечает за направление входящихHttpRequests на все остальные контроллеры и обработчики приложения.

DispatcherServlet Spring реализует этот шаблон и, следовательно, отвечает за правильную координациюHttpRequests для правых обработчиков.

С другой стороны,ContextLoaderListener запускается и закрывает корень SpringWebApplicationContext. Он связывает жизненный циклApplicationContext с жизненным цикломServletContext.. Мы можем использовать его для определения общих bean-компонентов, работающих в разных контекстах Spring.

Дополнительные сведения оDispatcherServlet см. Вto this tutorial.

Q20. Что такоеMultipartResolver и когда его использовать?

The MultipartResolver interface is used for uploading files. Инфраструктура Spring предоставляет одну реализациюMultipartResolver для использования с Commons FileUpload, а другую - для парсинга многостраничных запросов Servlet 3.0.

Используя их, мы можем поддерживать загрузку файлов в наших веб-приложениях.

Q21. Что такое Spring MVC Interceptor и как его использовать?

Spring MVC Interceptor позволяет нам перехватывать клиентский запрос и обрабатывать его в трех местах - до обработки, после обработки или после завершения (когда представление отображается) запроса.

Перехватчик может использоваться для сквозных задач и во избежание повторяющегося кода обработчика, такого как ведение журнала, изменение глобально используемых параметров в модели Spring и т. Д.

Подробности и различные реализации можно найти в статьеIntroduction to Spring MVC HandlerInterceptor.

Q22. Что такое Init Binder?

A method annotated with @InitBinder is used to customize a request parameter, URI template, and backing/command objects. Мы определяем это в контроллере, и это помогает контролировать запрос. In this method, we register and configure our custom PropertyEditors, a formatter, and validators.

В аннотации есть элемент «value». Если мы не установим его, аннотированные методы@InitBinder будут вызываться при каждом HTTP-запросе. Если мы установим значение, методы будут применяться только для определенных атрибутов команды / формы и / или параметров запроса, имена которых соответствуют элементу «value».

It’s important to remember that one of the arguments must be WebDataBinder. Другие аргументы могут быть любого типа, поддерживаемого методами-обработчиками, за исключением объектов команд / форм и соответствующих объектов результатов проверки.

Q23. Объясните совет контроллера

The @ControllerAdvice annotation allows us to write global code applicable to a wide range of controllers. Мы можем привязать диапазон контроллеров к выбранному пакету или конкретной аннотации.

По умолчанию@ControllerAdvice applies to the classes annotated with @Controller (or @RestController). У нас также есть несколько свойств, которые мы используем, если мы хотим быть более конкретными.

If we want to restrict applicable classes to a package, we should add the name of the package to the annotation:

@ControllerAdvice("my.package")
@ControllerAdvice(value = "my.package")
@ControllerAdvice(basePackages = "my.package")

Также возможно использовать несколько пакетов, но на этот раз нам нужно использовать массив вместоString.

Besides restricting to the package by its name, we can do it by using one of the classes or interfaces from that package:

@ControllerAdvice(basePackageClasses = MyClass.class)

Элемент «assignableTypes» применяет@ControllerAdvice к определенным классам, а элемент «annotations» - к конкретным аннотациям.

It’s noteworthy to remember that we should use it along with @ExceptionHandler. Эта комбинация позволит нам настроить глобальный и более конкретный механизм обработки ошибок без необходимости реализовывать его каждый раз для каждого класса контроллера.

Q24. Что делает аннотация@ExceptionHandler?

The @ExceptionHandler annotation allows us to define a method that will handle the exceptions. We may use the annotation independently, but it’s a far better option to use it together with the @ControllerAdvice. Таким образом, мы можем настроить глобальный механизм обработки ошибок. In this way, we don’t need to write the code for the exception handling within every controller.

Давайте посмотрим на пример из нашей статьи проError Handling for REST with Spring:

@ControllerAdvice
public class RestResponseEntityExceptionHandler
  extends ResponseEntityExceptionHandler {

    @ExceptionHandler(value = { IllegalArgumentException.class,
      IllegalStateException.class })
    protected ResponseEntity handleConflict(RuntimeException ex,
      WebRequest request) {
        String bodyOfResponse = "This should be application specific";
        return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(),
          HttpStatus.CONFLICT, request);
    }
}


Мы также должны отметить, что это предоставит методы@ExceptionHandler для всех контроллеров, которые выбрасываютIllegalArgumentException илиIllegalStateException. Исключения, объявленные с помощью@ExceptionHandler, должны соответствовать исключению, используемому в качестве аргумента метода. В противном случае механизм разрешения исключений не будет работать во время выполнения.

Здесь следует помнить, что для одного и того же исключения можно определить более одного@ExceptionHandler. Однако мы не можем сделать это в одном классе, поскольку Spring будет жаловаться, генерируя исключение и завершая работу с ошибкой при запуске.

С другой стороны,if we define those in two separate classes, the application will start, but it’ll use the first handler it finds, possibly the wrong one.

Q25. Обработка исключений в веб-приложениях

У нас есть три варианта обработки исключений в Spring MVC:

  • за исключение

  • на контроллер

  • глобально

Если во время обработки веб-запроса возникнет необработанное исключение, сервер вернет ответ HTTP 500. Чтобы предотвратить это,we should annotate any of our custom exceptions with the @ResponseStatus annotation. This kind of exceptions is resolved by HandlerExceptionResolver.

Это заставит сервер возвращать соответствующий HTTP-ответ с указанным кодом состояния, когда метод контроллера выдает наше исключение. Мы должны помнить, что мы не должны обрабатывать наше исключение где-то еще, чтобы этот подход сработал.

Another way to handle the exceptions is by using the @ExceptionHandler annotation. Мы добавляем методы@ExceptionHandler к любому контроллеру и используем их для обработки исключений, генерируемых внутри этого контроллера. Эти методы могут обрабатывать исключения без аннотации@ResponseStatus, перенаправлять пользователя в специальное представление ошибок или создавать полностью настраиваемый ответ на ошибку.

Мы также можем передать связанные с сервлетом объекты (HttpServletRequest,HttpServletResponse,HttpSession иPrincipal) в качестве параметров методов обработчика. Но мы должны помнить, что мы не можем напрямую указать объектModel в качестве параметра.

The third option for handling errors is by @ControllerAdvice classes. Это позволит нам применить те же методы, только на этот раз на уровне приложения, а не только для конкретного контроллера. Чтобы включить это, нам нужно использовать@ControllerAdvice и@ExceptionHandler вместе. Таким образом, обработчики исключений будут обрабатывать исключения, генерируемые любым контроллером.

Для получения более подробной информации по этой теме прочтите статьюError Handling for REST with Spring.

4. Заключение

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

Желаем удачи в любых предстоящих интервью!