1. Introduction
1.绪论
Spring MVC is the original web framework from Spring built on the Servlet API. It provides Model-View-Controller architecture that can be used to develop flexible web applications.
Spring MVC是Spring公司在Servlet API基础上建立的原始Web框架。它提供了模型-视图-控制器架构,可用于开发灵活的Web应用程序。
In this tutorial, we’ll focus on the questions related to it, as it is often a topic on a Spring developer job interview.
在本教程中,我们将重点讨论与之相关的问题,因为这常常是Spring开发者工作面试的一个话题。
For more questions on the Spring Framework, you can check out another Spring related article of our interview questions series.
关于Spring框架的更多问题,你可以查看我们的另一篇与Spring相关的文章面试问题系列>。
2. Basic Spring MVC Questions
2.基本的Spring MVC问题
Q1. Why Should We Use Spring MVC?
Q1.我们为什么要使用Spring MVC?
Spring MVC implements a clear separation of concerns that allows us to develop and unit test our applications easily.
Spring MVC实现了清晰的关注点分离,使我们能够轻松开发和单元测试我们的应用程序。
The concepts like:
的概念,如。
- Dispatcher Servlet
- Controllers
- View Resolvers
- Views, Models
- ModelAndView
- Model and Session Attributes
are completely independent of each other, and they are responsible for one thing only.
彼此完全独立,而且只对一件事负责。
Therefore, MVC gives us quite big flexibility. It’s based on interfaces (with provided implementation classes), and we can configure every part of the framework by using custom interfaces.
因此,MVC给了我们相当大的灵活性。它基于接口(提供实现类),我们可以通过使用自定义接口来配置框架的每个部分。
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.
另一件重要的事情是,我们并没有被束缚在特定的视图技术上(例如,JSP),而是可以选择我们最喜欢的技术。
Also, we don’t use Spring MVC only in web applications development but in the creation of RESTful web services as well.
此外,我们不仅在Web应用开发中使用Spring MVC,而且在创建RESTful Web服务中也使用它。
Q2. What Is the Role of the @Autowired Annotation?
问题2 @Autowired注释的作用是什么?
The @Autowired annotation can be used with fields or methods for injecting a bean by type. This annotation allows Spring to resolve and inject collaborating beans into your bean.
@Autowired注解可与字段或方法一起使用,用于按类型注入Bean。这个注解允许Spring解析并将协作的Bean注入到你的Bean中。
For more details, please refer to the tutorial about @Autowired in Spring.
欲了解更多详情,请参考关于@Autowired in Spring的教程。
Q3. Explain a Model Attribute
Q3.解释一个模型属性
The @ModelAttribute annotation is one of the most important annotations in 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.
@ModelAttribute注解是Spring MVC中最重要的注解之一。它将一个方法参数或方法返回值绑定到一个命名的模型属性上,然后将其暴露给Web视图。
If we use it at the method level, it indicates the purpose of that method is to add one or more model attributes.
如果我们在方法层面使用它,它表明该方法的目的是添加一个或多个模型属性。
On the other hand, when used as a method argument, it indicates the argument should be retrieved from the model. When not present, we should first instantiate it and then add it to the model. Once present in the model, we should populate the arguments fields from all request parameters that have matching names.
另一方面,当作为方法参数使用时,它表示该参数应该从模型中检索出来。当不存在时,我们应该首先将其实例化,然后将其添加到模型中。一旦出现在模型中,我们应该从所有具有匹配名称的请求参数中填充参数字段。
More about this annotation can be found in our article related to the @ModelAttribute annotation.
关于该注解的更多信息,可以在我们的与@ModelAttribute注解有关的文章中找到。
Q4. Explain the Difference Between @Controller and @RestController?
Q4.解释一下@Controller和@RestController之间的区别?
The main difference between the @Controller and @RestController annotations is that the @ResponseBody annotation is automatically included in the @RestController. This means that we don’t need to annotate our handler methods with the @ResponseBody. We need to do this in a @Controller class if we want to write response type directly to the HTTP response body.
@Controller和@RestController注解的主要区别是:@ResponseBody注解自动包含在@RestController中。这意味着我们不需要用@ResponseBody来注释我们的处理方法。如果我们想直接在HTTP响应体中写入响应类型,我们需要在@Controller类中这样做。
Q5. Describe a PathVariable
Q5.描述一个PathVariable
We can use the @PathVariable annotation as a handler method parameter in order to extract the value of a URI template variable.
我们可以使用@PathVariable注解作为处理方法参数,以提取URI模板变量的值。
For example, if we want to fetch a user by id from the www.mysite.com/user/123, we should map our method in the controller as /user/{id}:
例如,如果我们想从www.mysite.com/user/123中获取一个用户的ID,我们应该将控制器中的方法映射为/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. If we omit the value element, then the URI template variable name must match the method parameter name.
@PathVariable只有一个名为value的元素。它是可选的,我们用它来定义URI模板变量名。如果我们省略value元素,那么URI模板变量名称必须与方法参数名称相匹配。
It’s also allowed to have multiple @PathVariable annotations, either by declaring them one after another:
也允许有多个@PathVariable注解,可以通过一个接一个地声明它们。
@RequestMapping("/user/{userId}/name/{userName}")
public String handleRequest(@PathVariable String userId,
@PathVariable String userName, Model map) {}
or putting them all in a Map<String, String> or MultiValueMap<String, String>:
或者把它们都放在一个Map<String, String>或MultiValueMap<String, String>中。
@RequestMapping("/user/{userId}/name/{userName}")
public String handleRequest(@PathVariable Map<String, String> varsMap, Model map) {}
Q6. Validation Using Spring MVC
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, for example, is one of the JSR-303 implementations at our disposal.
Spring MVC默认支持JSR-303规范。我们需要将JSR-303及其实现依赖添加到我们的Spring MVC应用中。例如,Hibernate Validator就是我们可以使用的JSR-303实现之一。
JSR-303 is a specification of the Java API for bean validation, part of Jakarta EE and JavaSE, which ensures that properties of a bean meet specific criteria, using annotations such as @NotNull, @Min, and @Max. More about validation is available in the Java Bean Validation Basics article.
JSR-303是用于bean验证的Java API规范,是Jakarta EE和JavaSE的一部分,它使用@NotNull、@Min和@Max等注解,确保bean的属性符合特定标准。关于验证的更多信息,请参见Java Bean验证基础文章。
Spring offers the @Validator annotation and the BindingResult class. The Validator implementation will raise errors in the controller request handler method when we have invalid data. Then we may use the BindingResult class to get those errors.
Spring提供了@Validator注解和BindingResult类。当我们有无效的数据时,Validator实现将在控制器请求处理方法中引发错误。然后我们可以使用BindingResult类来获得这些错误。
Besides using the existing implementations, we can make our own. To do so, we create an annotation that conforms to the JSR-303 specifications first. Then, we implement the Validator class. Another way would be to implement Spring’s Validator interface and set it as the validator via @InitBinder annotation in Controller class.
除了使用现有的实现,我们还可以制作自己的实现。为此,我们首先创建一个符合JSR-303规范的注解。然后,我们实现Validator类。另一种方法是实现Spring的Validator接口,并通过@InitBinder注解在Controller类中将其设为验证器。
To check out how to implement and use your own validations, please see the tutorial regarding Custom Validation in Spring MVC.
要查看如何实现和使用自己的验证,请参见有关Spring MVC中的自定义验证的教程。
Q7. What Are the @RequestBody and the @ResponseBody Annotations?
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 automatically deserializes incoming HTTP Request to the Java object using Http Message Converters.
@RequestBody注解,作为处理方法参数使用,将HTTP请求体绑定到传输或域对象上。Spring使用Http消息转换器自动将传入的HTTP请求反序列化为Java对象。
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. We’ll not put it in a Model, and Spring won’t interpret as a view name.
当我们在Spring MVC控制器中的处理方法上使用@ResponseBody注解时,它表明我们将把该方法的返回类型直接写入HTTP响应体中。我们不会把它放在Model中,Spring也不会把它解释为一个视图名称。
Please check out the article on @RequestBody and @ResponseBody to see more details about these annotations.
请查看@RequestBody和@ResponseBody的文章,看看关于这些注释的更多细节。
Q8. Explain Model, ModelMap and ModelAndView?
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. It then treats those values as if they were within a Map. We should note that in Model (ModelMap) we can only store data. We put data in and return a view name.
Model接口定义了一个模型属性的持有者。ModelMap具有类似的目的,它能够传递一个值的集合。然后,它将这些值当作是在Map中。我们应该注意,在Model(ModelMap)中我们只能存储数据。我们把数据放进去并返回一个视图名称。
On the other hand, with the ModelAndView, we return the object itself. We set all the required information, like the data and the view name, in the object we’re returning.
另一方面,使用ModelAndView,我们返回对象本身。我们在返回的对象中设置所有需要的信息,如数据和视图名称。
You can find more details in the article on Model, ModelMap, and ModelView.
你可以在Model、ModelMap和ModelView的文章中找到更多细节。
Q9. Explain SessionAttributes and SessionAttribute
Q9.解释SessionAttributes和SessionAttribute
The @SessionAttributes annotation is used for storing the model attribute in the user’s session. We use it at the controller class level, as shown in our article about the Session Attributes in Spring MVC:
@SessionAttributes注解用于在用户会话中存储模型属性。我们在控制器类级别上使用它,如我们关于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
}
In the previous example, the model attribute ‘todos‘ will be added to the session if the @ModelAttribute and the @SessionAttributes have the same name attribute.
在前面的例子中,如果@ModelAttribute和@SessionAttributes有相同的名称属性,模型属性’todos‘将被添加到会话中。
If we want to retrieve the existing attribute from a session that is managed globally, we’ll use @SessionAttribute annotation as a method parameter:
如果我们想从一个全局管理的会话中检索现有属性,我们将使用@SessionAttribute注解作为方法参数。
@GetMapping
public String getTodos(@SessionAttribute("todos") TodoList todos) {
// method body
return "todoView";
}
Q10. What Is the Purpose of @EnableWebMVC?
Q10.@EnableWebMVC的目的是什么?
The @EnableWebMvc annotation’s purpose is to enable Spring MVC via Java configuration. It’s equivalent to <mvc: annotation-driven> in an XML configuration. This annotation imports Spring MVC Configuration from WebMvcConfigurationSupport. It enables support for @Controller-annotated classes that use @RequestMapping to map incoming requests to a handler method.
@EnableWebMvc注解的目的是通过Java配置启用Spring MVC。它相当于XML配置中的<mvc: annotation-driven>/em>。该注解从WebMvcConfigurationSupport导入Spring MVC配置。它能够支持@Controller注释的类,这些类使用@RequestMapping将传入的请求映射到一个处理方法。
You can learn more about this and similar annotations in our Guide to the Spring @Enable Annotations.
您可以在我们的Guide to the Spring @Enable Annotations中了解更多关于该注释和类似注释的信息。
Q11. What Is ViewResolver in Spring?
Q11.什么是Spring中的ViewResolver?
The ViewResolver enables an application to render models in the browser – without tying the implementation to a specific view technology – by mapping view names to actual views.
ViewResolver使应用程序能够在浏览器中渲染模型–无需将实现与特定的视图技术相联系–通过将视图名称映射到实际视图。
For more details about the ViewResolver, have a look at our Guide to the ViewResolver in Spring MVC.
有关ViewResolver的更多细节,请查看我们的Spring MVC中的ViewResolver指南。
Q12. What Is the BindingResult?
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. It’s easy to invoke — we just need to ensure that we put it as a parameter right after the form object we’re validating. The optional Model parameter should come after the BindingResult, as it can be seen in the custom validator tutorial:
BindingResult是一个来自org.springframework.validation包的接口,表示绑定结果。我们可以用它来检测和报告提交表单中的错误。它很容易调用 – 我们只需要确保把它作为一个参数放在我们要验证的表单对象之后即可。可选的Model参数应该放在BindingResult之后,正如在custom validator教程中所看到的那样。
@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. Then it’ll pick up the validation annotations and invoke the validator. Finally, it’ll put found errors in the BindingResult and add the latter to the view model.
当Spring看到@Valid注解时,它将首先尝试为被验证的对象找到验证器。然后它将拾取验证注解并调用验证器。最后,它将把发现的错误放在BindingResult中,并把后者添加到视图模型中。
Q13. What Is a Form Backing Object?
Q13.什么是表格支持对象?
The form backing object or a Command Object is just a POJO that collects data from the form we’re submitting.
表单支持对象或命令对象只是一个POJO,它从我们要提交的表单中收集数据。
We should keep in mind that it doesn’t contain any logic, only data.
我们应该牢记,它不包含任何逻辑,只有数据。
To learn how to use form backing object with the forms in Spring MVC, please take a look at our article about Forms in Spring MVC.
要了解如何在Spring MVC中使用表单支持对象,请看我们关于Spring MVC中的表单的文章。
Q14. What Is the Role of the @Qualifier Annotation?
Q14.@Qualifier注释的作用是什么?
It is used simultaneously with the @Autowired annotation to avoid confusion when multiple instances of a bean type are present.
它与@Autowired注解同时使用,以避免在一个bean类型的多个实例出现时出现混淆。
Let’s see an example. We declared two similar beans in XML config:
让我们看一个例子。我们在XML config中声明了两个类似的bean。
<bean id="person1" class="com.baeldung.Person" >
<property name="name" value="Joe" />
</bean>
<bean id="person2" class="com.baeldung.Person" >
<property name="name" value="Doe" />
</bean>
When we try to wire the bean, we’ll get an org.springframework.beans.factory.NoSuchBeanDefinitionException. To fix it, we need to use @Qualifier to tell Spring about which bean should be wired:
当我们试图连接Bean时,我们会得到一个org.springframework.beans.factory.NoSuchBeanDefinitionException.为了解决这个问题,我们需要使用@Qualifier来告诉Spring关于哪个Bean应该被连接。
@Autowired
@Qualifier("person1")
private Person person;
Q15. What Is the Role of the @Required Annotation?
Q15.@Required注释的作用是什么?
The @Required annotation is used on setter methods, and it indicates that the bean property that has this annotation must be populated at configuration time. Otherwise, the Spring container will throw a BeanInitializationException exception.
@Required注解用于setter方法,它表示具有此注解的Bean属性必须在配置时被填充。否则,Spring容器将抛出一个BeanInitializationException异常。
Also, @Required differs from @Autowired – as it is limited to a setter, whereas @Autowired is not. @Autowired can be used to wire with a constructor and a field as well, while @Required only checks if the property is set.
另外,@Required与@Autowired不同–因为它只限于一个setter,而@Autowired则不是。@Autowired也可以用来与构造函数和字段进行连接,而@Required只检查该属性是否被设置。
Let’s see an example:
让我们看一个例子。
public class Person {
private String name;
@Required
public void setName(String name) {
this.name = name;
}
}
Now, the name of the Person bean needs to be set in XML config like this:
现在,Person Bean的name需要像这样在XML config中设置。
<bean id="person" class="com.baeldung.Person">
<property name="name" value="Joe" />
</bean>
Please note that @Required doesn’t work with Java based @Configuration classes by default. If you need to make sure that all your properties are set, you can do so when you create the bean in the @Bean annotated methods.
请注意,@Required默认情况下不与基于Java的@Configuration类一起工作。如果你需要确保所有的属性都被设置,你可以在@Bean注解的方法中创建Bean时这样做。
Q16. Describe the Front Controller Pattern
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.
在前台控制器模式中,所有的请求将首先进入前台控制器,而不是Servlet。它将确保响应已经准备好,并将其发回给浏览器。这样,我们就有一个地方可以控制来自外部世界的一切。。
The front controller will identify the servlet that should handle the request first. Then, when it gets the data back from the servlet, it’ll decide which view to render and, finally, it’ll send the rendered view back as a response:
前端控制器将首先识别应该处理请求的Servlet。然后,当它从servlet那里得到数据后,它将决定渲染哪个视图,最后,它将把渲染好的视图作为一个响应送回来。
To see the implementation details, please check out our Guide to the Front Controller Pattern in Java.
要查看实施细节,请查看我们的Java中的Front Controller模式指南。
Q17. What Are Model 1 and Model 2 Architectures?
Q17.什么是模型1和模型2架构?
Model 1 and Model 2 represent two frequently used design models when it comes to designing Java Web Applications.
模型1和模型2代表了在设计Java Web应用程序时经常使用的两种设计模型。
In Model 1, a request comes to a servlet or JSP where it gets handled. The servlet or the JSP processes the request, handles business logic, retrieves and validates data, and generates the response:
在模式1中,一个请求来到一个Servlet或JSP,在那里得到处理。Servlet或JSP处理请求,处理业务逻辑,检索和验证数据,并生成响应。
Since this architecture is easy to implement, we usually use it in small and simple applications.
由于这种架构易于实现,我们通常将其用于小型和简单的应用。
On the other hand, it isn’t convenient for large-scale web applications. The functionalities are often duplicated in JSPs where business and presentation logic are coupled.
另一方面,它对于大规模的网络应用来说并不方便。在业务和表现逻辑耦合的JSP中,功能往往是重复的。
The Model 2 is based on the Model View Controller design pattern and it separates the view from the logic that manipulates the content.
模型2基于模型-视图-控制器设计模式,它将视图与操作内容的逻辑分开。
Furthermore, we can distinguish three modules in the MVC pattern: the model, the view, and the controller. The model is representing the dynamic data structure of an application. It’s responsible for the data and business logic manipulation. The view is in charge of displaying the data, while the controller serves as an interface between the previous two.
此外,我们可以区分MVC模式中的三个模块:模型、视图和控制器。模型代表一个应用程序的动态数据结构。它负责数据和业务逻辑的操作。视图负责显示数据,而控制器作为前两者之间的接口。
In Model 2, a request is passed to the controller, which handles the required logic in order to get the right content that should be displayed. The controller then puts the content back into the request, typically as a JavaBean or a POJO. It also decides which view should render the content and finally passes the request to it. Then, the view renders the data:
在模型2中,一个请求被传递给控制器,控制器处理所需的逻辑,以获得应该显示的正确内容。然后,控制器将内容放回请求中,通常是作为一个JavaBean或POJO。它还决定哪个视图应该渲染内容,最后将请求传递给它。然后,视图就会渲染数据。
3. Advanced Spring MVC Questions
3.高级Spring MVC问题
Q18. What’s the Difference Between @Controller, @Component, @Repository, and @Service Annotations in Spring?
Q18.Spring中的@Controller、@Component、@Repository和@Service注解之间有什么区别?
According to the official Spring documentation, @Component is a generic stereotype for any Spring-managed component. @Repository, @Service, and @Controller are specializations of @Component for more specific use cases, for example, in the persistence, service, and presentation layers, respectively.
根据Spring官方文档,@Component是任何Spring管理的组件的通用定型。@Repository、@Service和@Controller是@Component的专门化,用于更具体的使用情况,例如,分别在持久层、服务层和表现层。
Let’s take a look at specific use cases of last three:
让我们来看看后三者的具体用例。
- @Controller – indicates that the class serves the role of a controller, and detects @RequestMapping annotations within the class
- @Service – indicates that the class holds business logic and calls methods in the repository layer
- @Repository – indicates that the class defines a data repository; its job is to catch platform-specific exceptions and re-throw them as one of Spring’s unified unchecked exceptions
Q19. What Are DispatcherServlet and ContextLoaderListener?
Q19.什么是DispatcherServlet和ContextLoaderListener?
Simply put, in the Front Controller design pattern, a single controller is responsible for directing incoming HttpRequests to all of an application’s other controllers and handlers.
简单地说,在前台控制器设计模式中,一个控制器负责将传入的HttpRequests引导到应用程序的所有其他控制器和处理程序。
Spring’s DispatcherServlet implements this pattern and is, therefore, responsible for correctly coordinating the HttpRequests to the right handlers.
Spring的DispatcherServlet实现了这种模式,因此,它负责将HttpRequests正确地协调到正确的处理程序。
On the other hand, ContextLoaderListener starts up and shuts down Spring’s root WebApplicationContext. It ties the lifecycle of ApplicationContext to the lifecycle of the ServletContext. We can use it to define shared beans working across different Spring contexts.
另一方面,ContextLoaderListener启动和关闭Spring的根WebApplicationContext。它将ApplicationContext的生命周期与ServletContext的生命周期联系起来。我们可以用它来定义在不同Spring上下文中工作的共享Bean。
For more details on DispatcherServlet, please refer to this tutorial.
关于DispatcherServlet的更多细节,请参考本教程。
Q20. What Is a MultipartResolver and When Should We Use It?
Q20 什么是MultipartResolver,我们什么时候应该使用它?
The MultipartResolver interface is used for uploading files. The Spring framework provides one MultipartResolver implementation for use with Commons FileUpload and another for use with Servlet 3.0 multipart request parsing.
MultipartResolver接口用于上传文件。Spring框架提供了一个MultipartResolver实现,用于Commons FileUpload,另一个用于Servlet 3.0多部分请求解析。
Using these, we can support file uploads in our web applications.
利用这些,我们可以在我们的网络应用中支持文件上传。
Q21. What Is Spring MVC Interceptor and How to Use It?
Q21.什么是Spring MVC拦截器以及如何使用它?
Spring MVC Interceptors allow us to intercept a client request and process it at three places – before handling, after handling, or after completion (when the view is rendered) of a request.
Spring MVC拦截器允许我们拦截一个客户端请求,并在三个地方进行处理–在处理之前、处理之后或完成之后(当视图被渲染时)的请求。
The interceptor can be used for cross-cutting concerns and to avoid repetitive handler code like logging, changing globally used parameters in Spring model, etc.
拦截器可用于跨领域的关注,并避免重复的处理程序代码,如记录、改变Spring模型中全局使用的参数等。
For details and various implementations, take a look at Introduction to Spring MVC HandlerInterceptor article.
有关详细信息和各种实现,请查看Introduction to Spring MVC HandlerInterceptor文章。
Q22. What Is an Init Binder?
Q22.什么是Init Binder?
A method annotated with @InitBinder is used to customize a request parameter, URI template, and backing/command objects. We define it in a controller and it helps in controlling the request. In this method, we register and configure our custom PropertyEditors, a formatter, and validators.
用@InitBinder注解的方法用于定制一个请求参数、URI模板和支持/命令对象。我们在控制器中定义它,它有助于控制请求。在这个方法中,我们注册并配置我们的自定义PropertyEditors,一个格式化器和验证器。
The annotation has the ‘value‘ element. If we don’t set it, the @InitBinder annotated methods will get called on each HTTP request. If we set the value, the methods will be applied only for particular command/form attributes and/or request parameters whose names correspond to the ‘value‘ element.
该注解有’value‘元素。如果我们不设置它,@InitBinder注释的方法将在每个HTTP请求中被调用。如果我们设置了这个值,这些方法将只适用于特定的命令/表单属性和/或请求参数,这些参数的名称与’value‘元素对应。
It’s important to remember that one of the arguments must be WebDataBinder. Other arguments can be of any type that handler methods support except for command/form objects and corresponding validation result objects.
重要的是要记住,其中一个参数必须是WebDataBinder。其他参数可以是处理方法支持的任何类型,除了命令/表单对象和相应的验证结果对象。
Q23. Explain a Controller Advice
Q23.解释一下控制器的建议
The @ControllerAdvice annotation allows us to write global code applicable to a wide range of controllers. We can tie the range of controllers to a chosen package or a specific annotation.
@ControllerAdvice注解允许我们编写适用于各种控制器的全局代码。我们可以将控制器的范围与选定的包或特定的注解联系起来。
By default, @ControllerAdvice applies to the classes annotated with @Controller (or @RestController). We also have a few properties that we use if we want to be more specific.
默认情况下,@ControllerAdvice适用于用@Controller(或@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")
It’s also possible to use multiple packages, but this time we need to use an array instead of the String.
也可以使用多个包,但这次我们需要使用一个数组而不是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)
The ‘assignableTypes‘ element applies the @ControllerAdvice to the specific classes, while ‘annotations‘ does it for particular annotations.
assignableTypes‘元素将@ControllerAdvice应用于特定的类,而’annotations‘则针对特定的注释。
It’s noteworthy to remember that we should use it along with @ExceptionHandler. This combination will enable us to configure a global and more specific error handling mechanism without the need to implement it every time for every controller class.
值得注意的是,我们应该把它和@ExceptionHandler一起使用。这种组合将使我们能够配置一个全局的、更具体的错误处理机制,而不需要每次都为每个控制器类实现它。
Q24. What Does the @ExceptionHandler Annotation Do?
Q24.@ExceptionHandlerAnnotation做什么?
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. Thus, we can set up a global error handling mechanism. In this way, we don’t need to write the code for the exception handling within every controller.
@ExceptionHandler注解允许我们定义一个处理异常的方法。我们可以独立使用该注解,但将其与@ControllerAdvice一起使用是更好的选择。因此,我们可以设置一个全局的错误处理机制。这样一来,我们就不需要在每个控制器中编写异常处理的代码。
Let’s take a look at the example from our article about Error Handling for REST with Spring:
让我们来看看我们关于用Spring处理REST的错误文章中的例子。
@ControllerAdvice
public class RestResponseEntityExceptionHandler
extends ResponseEntityExceptionHandler {
@ExceptionHandler(value = { IllegalArgumentException.class,
IllegalStateException.class })
protected ResponseEntity<Object> handleConflict(RuntimeException ex,
WebRequest request) {
String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(),
HttpStatus.CONFLICT, request);
}
}
We should also note that this will provide @ExceptionHandler methods to all controllers that throw IllegalArgumentException or IllegalStateException. The exceptions declared with @ExceptionHandler should match the exception used as the argument of the method. Otherwise, the exception resolving mechanism will fail at runtime.
我们还应该注意,这将为所有抛出@ExceptionHandler的控制器提供IllegalArgumentException或IllegalStateException的方法。用@ExceptionHandler声明的异常应该与作为方法参数的异常相匹配。否则,异常解析机制将在运行时失败。
One thing to keep in mind here is that it’s possible to define more than one @ExceptionHandler for the same exception. We can’t do it in the same class though since Spring would complain by throwing an exception and failing on startup.
这里需要记住的一点是,我们可以为同一个异常定义多个@ExceptionHandler。但我们不能在同一个类中这样做,因为Spring会通过抛出异常并在启动时失败来抱怨。
On the other hand, 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. Exception Handling in Web Applications
Q25.网络应用程序中的异常处理
We have three options for exceptions handling in Spring MVC:
在Spring MVC中,我们有三种处理异常的方法。
- per exception
- per controller
- globally
If an unhandled exception is thrown during web request processing, the server will return an HTTP 500 response. To prevent this, we should annotate any of our custom exceptions with the @ResponseStatus annotation. This kind of exceptions is resolved by HandlerExceptionResolver.
如果在Web请求处理过程中抛出一个未处理的异常,服务器将返回一个HTTP 500响应。为了防止这种情况,我们应该用@ResponseStatus注解来注释我们的任何自定义异常。这类异常由HandlerExceptionResolver解决。
This will cause the server to return an appropriate HTTP response with the specified status code when a controller method throws our exception. We should keep in mind that we shouldn’t handle our exception somewhere else for this approach to work.
当一个控制器方法抛出我们的异常时,这将导致服务器返回一个适当的HTTP响应,并指定状态代码。我们应该记住,我们不应该在其他地方处理我们的异常,这种方法才会有效。
Another way to handle the exceptions is by using the @ExceptionHandler annotation. We add @ExceptionHandler methods to any controller and use them to handle the exceptions thrown from inside that controller. These methods can handle exceptions without the @ResponseStatus annotation, redirect the user to a dedicated error view, or build a totally custom error response.
另一种处理异常的方法是使用@ExceptionHandler注解。我们将@ExceptionHandler方法添加到任何控制器中,用它们来处理从该控制器中抛出的异常。这些方法可以在没有@ResponseStatus注解的情况下处理异常,将用户重定向到一个专门的错误视图,或者建立一个完全自定义的错误响应。
We can also pass in the servlet-related objects (HttpServletRequest, HttpServletResponse, HttpSession, and Principal) as the parameters of the handler methods. But, we should remember that we can’t put the Model object as the parameter directly.
我们也可以传入与servlet相关的对象(HttpServletRequest, HttpServletResponse, HttpSession, 和Principal)作为处理方法的参数。但是,我们应该记住,我们不能把Model对象直接作为参数。
The third option for handling errors is by @ControllerAdvice classes. It’ll allow us to apply the same techniques, only this time at the application level and not only to the particular controller. To enable this, we need to use the @ControllerAdvice and the @ExceptionHandler together. This way exception handlers will handle exceptions thrown by any controller.
处理错误的第三个选择是通过@ControllerAdvice类。它将允许我们应用同样的技术,只是这次是在应用层面,而不仅仅是针对特定的控制器。为了实现这一点,我们需要将@ControllerAdvice和@ExceptionHandler一起使用。这样,异常处理程序将处理任何控制器抛出的异常。
For more detailed information on this topic, go through the Error Handling for REST with Spring article.
有关该主题的更多详细信息,请查阅Error Handling for REST with Spring文章。
4. Conclusion
4.结论
In this article, we’ve explored some of the Spring MVC related questions that could come up at the technical interview for Spring developers. You should take these questions into account as a starting point for further research since this is by no means an exhaustive list.
在这篇文章中,我们探讨了一些Spring MVC相关的问题,这些问题可能会在Spring开发者的技术面试中出现。你应该把这些问题作为进一步研究的起点,因为这绝不是一个详尽的列表。
We wish you good luck in any upcoming interviews!
我们祝愿你在接下来的面试中取得好成绩!