spring - mvc - 1
spring mvc
1.@Autowired
@Component
public class FooService {
@Autowired
private FooFormatter fooFormatter;
}
2.通过@Qualifier自动装配
例如,让我们看看如何使用@Qualifier注释来指示所需的 bean。
首先,我们将定义 2 个Formatter类型的 bean :
@Component("fooFormatter")
public class FooFormatter implements Formatter {
public String format() {
return "foo";
}
}
@Component("barFormatter")
public class BarFormatter implements Formatter {
public String format() {
return "bar";
}
}
我们可以通过使用@Qualifier注释缩小实现范围来避免这种情况:
public class FooService {
@Autowired
@Qualifier("fooFormatter")
private Formatter formatter;
}
当有多个相同类型的 bean 时,最好使用@Qualifier以避免歧义。
请注意, @Qualifier注释的值与我们的FooFormatter实现的@Component注释中声明的名称匹配。
3.通过自定义限定符自动装配
Spring还允许我们创建自己的自定义@Qualifier注释。为此,我们应该为@Qualifier注释提供定义:
@Qualifier
@Target({
ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface FormatterType {
String value();
}
然后我们可以在各种实现中使用FormatterType 来指定自定义值:
@FormatterType("Foo")
@Component
public class FooFormatter implements Formatter {
public String format() {
return "foo";
}
}
@FormatterType("Bar")
@Component
public class BarFormatter implements Formatter {
public String format() {
return "bar";
}
}
最后,我们的自定义限定符注释已准备好用于自动装配:
@Component
public class FooService {
@Autowired
@FormatterType("Foo")
private Formatter formatter;
}
@Target元注释中指定的值限制了限定符的应用位置,在我们的示例中是字段、方法、类型和参数。
@Qualifier与@Primary
还有另一个名为@Primary的注释 ,当依赖注入存在歧义时,我们可以使用它来决定注入哪个 bean。
该注释定义了存在多个相同类型的 bean 时的偏好。除非另有说明,否则将使用与@Primary注释关联的 bean 。
让我们看一个例子:
@Configuration
public class Config {
@Bean
public Employee johnEmployee() {
return new Employee("John");
}
@Bean
@Primary
public Employee tonyEmployee() {
return new Employee("Tony");
}
}
在此示例中,两个方法都返回相同的Employee类型。Spring 将注入的 bean 是tonyEmployee方法返回的 bean 。这是因为它包含@Primary注释。当我们想要指定默认情况下应注入某种类型的 bean时,此注释非常有用。
如果我们在某个注入点需要其他 bean,我们需要特别指出。我们可以通过@Qualifier注释来做到这一点。例如,我们可以通过使用@Qualifier注释来指定要使用johnEmployee方法返回的 bean 。
值得注意的是,如果@Qualifier和@Primary注解同时存在,那么@Qualifier注解将优先。基本上,@Primary定义了默认值,而@Qualifier则非常具体。
让我们看看使用@Primary注释的另一种方式,这次使用最初的示例:
@Component
@Primary
public class FooFormatter implements Formatter {
//...
}
@Component
public class BarFormatter implements Formatter {
//...
}
在这种情况下,@Primary注释被放置在实现类之一中,并将消除场景的歧义。
4.解释模型属性 @ModelAttribute注解是 Spring MVC中最重要的注解之一
@ModelAttribute注释
5.解释一下@Controller和@RestController之间的区别
@Controller和@RestController注释之间的主要区别在于@ResponseBody注释自动包含在@RestController中。这意味着我们不需要使用@ResponseBody注释我们的处理程序方法。如果我们想将响应类型直接写入 HTTP 响应正文,我们需要在 @Controller类中执行此操作。
6.描述一个 路径变量 @PathVariable
我们可以使用@PathVariable注释作为处理程序方法参数,以便提取 URI 模板变量的值。
例如,如果我们想通过 id 从www.mysite.com/user/123获取用户,我们应该将控制器中的方法映射为/user/{id}:
@RequestMapping("/user/{id}")
public String handleRequest(@PathVariable("id") String userId, Model map) {}
@PathVariable只有一个名为 value的元素。它是可选的,我们用它来定义 URI 模板变量 name。如果我们省略 value 元素,则 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<String, String> varsMap, Model map) {}
7.使用 Spring MVC 进行验证
创建自定义验证器需要推出我们自己的注释并在我们的模型中使用它来强制执行验证规则。
因此,让我们创建自定义验证器来检查电话号码。电话号码必须是至少 8 位数字,但不超过 11 位数字。
让我们创建一个新的@interface 来定义我们的注释:
@Documented
@Constraint(validatedBy = ContactNumberValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ContactNumberConstraint {
String message() default "Invalid phone number";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
使用@Constraint注释,我们定义了将验证我们的字段的类。message ()是显示在用户界面中的错误消息。最后,附加代码大部分是样板代码,以符合 Spring 标准。
现在让我们创建一个验证器类来强制执行验证规则:
public class ContactNumberValidator implements
ConstraintValidator<ContactNumberConstraint, String> {
@Override
public void initialize(ContactNumberConstraint contactNumber) {
}
@Override
public boolean isValid(String contactField,
ConstraintValidatorContext cxt) {
return contactField != null && contactField.matches("[0-9]+")
&& (contactField.length() > 8) && (contactField.length() < 14);
}
}
验证类实现ConstraintValidator接口,还必须实现isValid方法;我们在这个方法中定义了验证规则。
当然,我们在这里使用一个简单的验证规则来展示验证器的工作原理。
ConstraintValidator定义验证给定对象的给定约束的逻辑。实施必须遵守以下限制:
对象必须解析为非参数化类型
对象的泛型参数必须是无界通配符类型
8.@ExceptionHandler注解
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@NotBlank(message = "Name is mandatory")
private String name;
@NotBlank(message = "Email is mandatory")
private String email;
// standard constructors / setters / getters / toString
}
@ExceptionHandler注解允许我们通过一种方法处理指定类型的异常。
因此,我们可以用它来处理验证错误:
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Map<String, String> handleValidationExceptions(
MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach((error) -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return errors;
}
我们指定MethodArgumentNotValidException异常作为要处理的异常。因此,当指定的User对象无效时,Spring Boot 将调用此方法。
该方法将每个无效字段的名称和验证后错误消息存储在Map 中。接下来,它将Map作为 JSON 表示形式发送回客户端以进行进一步处理。
简而言之,REST 控制器允许我们轻松处理对不同端点的请求、验证User对象并以 JSON 格式发送响应。
该设计足够灵活,可以通过多个 Web 层处理控制器响应,范围从Thymeleaf等模板引擎到Angular等全功能 JavaScript 框架。
9.什么是@RequestBody和 @ResponseBody注释
@RequestBody注释用作处理程序方法参数,将 HTTP 请求正文绑定到传输或域对象。Spring 使用 Http 消息转换器自动将传入的 HTTP 请求反序列化到 Java 对象。
当我们在 Spring MVC 控制器中的处理方法上使用@ResponseBody注解时,它表明我们将该方法的返回类型直接写入 HTTP 响应正文。我们不会将其放入Model中,Spring 也不会将其解释为视图名称。
10.解释一下Model、ModelMap和ModelAndView
Model接口定义了模型属性的持有者。ModelMap具有类似的用途,能够传递值的集合。然后,它将这些值视为在Map中。我们应该注意,在 模型(ModelMap)中我们只能存储数据。我们放入数据并返回视图名称。
另一方面,使用ModelAndView,我们返回对象本身。我们在返回的对象中设置所有必需的信息,例如数据和视图名称。
您可以在有关 Model、ModelMap和ModelView的文章中找到更多详细信息 。
Model是一个接口,它的实现类为ExtendedModelMap,继承ModelMap类
public class ExtendedModelMap extends ModelMap implements Model
ModelMap继承LinkedHashMap,spring框架自动创建实例并作为controller的入参,用户无需自己创建
public class ModelMap extends LinkedHashMap
ModelAndView顾名思义,ModelAndView指模型和视图的集合,既包含模型 又包含视图;ModelAndView的实例是开发者自己手动创建的,这也是和ModelMap主要不同点之一;ModelAndView其实就是两个作用,一个是指定返回页面,另一个是在返回页面的同时添加属性;
Model与ModelMap其实都是实现了hashMap,并且用法都是一样的,它可以直接接收前台传过来的参数,后台直接获取。;两者都是spring在请求时自动生成,拿来用便可;ModelAndView就是在两者的基础上可以指定返回页面;
赋值能力 ModelAndView > Model/ModelMap>request ;
@ModelAttribute用于接收前台传递到后台的参数,它是简化了参数的传递。它会把请求参数的值直接赋给对应变量,绑定请求参数到指定对象 ,它会将表单中的请求参数绑定的指定的对象中,这样的话,对象就可以接收到请求的值,并且做一些操作。
11. 解释SessionAttributes和SessionAttribute
@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
}
在前面的示例中,如果@ModelAttribute和@SessionAttributes具有相同的 name 属性,则模型属性“ todos ”将被添加到会话中。
如果我们想从全局管理的会话中检索现有属性,我们将使用@SessionAttribute注释作为方法参数:
@GetMapping
public String getTodos(@SessionAttribute("todos") TodoList todos) {
// method body
return "todoView";
}
12.@EnableWebMVC的目的是什么?
@EnableWebMvc注解的目的是通过 Java配置启用 Spring MVC。它相当于XML配置中的mvc:annotation-driven 。此注释从WebMvcConfigurationSupport导入 Spring MVC 配置。它支持使用@RequestMapping将传入请求映射到处理程序方法的@Controller注释类。
您可以在我们的Spring @Enable Annotations指南中了解有关此注释和类似注释的更多信息 。
13.一些spring mvc的注解
@EnableWebMvc
@EnableWebMvc注释用于在应用程序中启用 Spring MVC ,并通过从WebMvcConfigurationSupport导入 Spring MVC 配置来工作。
具有类似功能的 XML 等效项是mvc:annotation-driven/。
配置可以通过实现WebMvcConfigurer 的@Configuration类进行自定义:
@Configuration
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters) {
converters.add(new MyHttpMessageConverter());
}
// ...
}