Spring MVC的常用注解

在Spring中,对象无需自己查找或创建与其所关联的其他对象。相反,容器负责把需要相互协作的对象引用赋予各个对象。创建应用对象之间协作关系的行为通常称为装配(wiring),这也是依赖注入(DI)的本质。

目录

1、自定义组件类

2、装配Bean

@Configuration

@ComponentScan和@ComponentScans

@Import和@ImportResource

@Value

@Autowired (属业spring的)

required属性

@Autowired 注解接口

@Resource(这个注解属于J2EE的)

@PostConstruct 和 @PreDestory 

3、请求映射

@RequestMapping

RequestMapping的属性

@PathVariable

@RequestParam

@RequestParam三个参数

@CookieValue

@RequestBody

作用: 

使用时机:

@ResponseBody

重定向和转发

@SessionAttributes

@ModelAttribute


1、自定义组件类

@Controller标注一个控制器组件类。@Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。

@Service标注一个业务层组件类。
@Repository标注一个dao持久层组件类。
@Component标注一个普通的Spring Bean类。 
@RestController注解是@Controller和@ResponseBody的合集,表示这是个控制器bean,并且是将函数的返回值直接填入HTTP响应体中,是REST风格的控制器。

以@Controller为例

@Controller("test")
//@Controller   /*相当于@Controller("testController")*/
@Scope("prototype") 
public class TestController {
    @RequestMapping("/test")
    public String test(){
        return "test";
    }
 
}
  1. 组件命名,①手动指定名称,例@Controller("testController")*。②如果不使用命名,而SpringMVC会默认把类名的头一个字母小写(类名TestController,组件名testController)。③当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致(类名CDPlayer,组件名CDPlayer)

  2. 组件作用域范围@Scope(singleton,prototype,request,session,global session),默认是单例模式,即scope="singleton"。
    ①.singleton单例模式,全局有且仅有一个实例
    ②.prototype原型模式,每次获取Bean的时候会有一个新的实例
    ③.request表示请求,即在一次http请求中,被注解的Bean都是同一个Bean,不同的请求是不同的Bean;
    ④.session表示会话,即在同一个会话中,被注解的Bean都是使用的同一个Bean,不同的会话使用不同的Bean。
    ⑤.global session

2、装配Bean

     Spring如何发现bean,定义普通java类,定义第三方bean,注入指定bean(名称,类型),bean的初始化和销毁。

@Configuration

从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class TestConfiguration {
    public TestConfiguration() {
        System.out.println("TestConfiguration容器启动初始化。。。");
    }

    // @Bean注解注册bean,同时可以指定初始化和销毁方法
    // @Bean(name="testBean",initMethod="start",destroyMethod="cleanUp")
    @Bean
    @Scope("prototype")
    public TestBean testBean() {
        return new TestBean();
    }
}

@ComponentScan和@ComponentScans

创建一个配置类,在配置类上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置类。

  1. 指定要扫描的包(使用@ComponentScan 的 valule 属性来配置)
  2. 使用 excludeFilters 来按照规则排除某些包的扫描。
  3. 使用 includeFilters 来按照规则只包含某些包的扫描。
package io.mieux.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
/*
excludeFilters 的参数是一个 Filter[] 数组,然后指定 FilterType 的类型为 ANNOTATION,也就是通过
注解来过滤,最后的 value 则是Controller 注解类。配置之后,在 spring 扫描的时候,就会跳过 io.mieux 
包下,所有被 @Controller 注解标注的类。
*/
@ComponentScan(value = "io.mieux",
        excludeFilters = {@Filter(type = FilterType.ANNOTATION,
        value = {Controller.class})})
public class BeanConfig {

}

如果使用的 jdk8,则可以直接添加多个 @ComponentScan 来添加多个扫描规则,但是在配置类中要加上 @Configuration 注解,否则无效。

package io.mieux.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@ComponentScan(value = "io.mieux.controller")
@ComponentScan(value = "io.mieux.service")
@Configuration
public class BeanConfig {

}

使用 @ComponentScans 来添加多个 @ComponentScan,从而实现添加多个扫描规则。同样,也需要加上 @Configuration 注解,否则无效。

package io.mieux.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;

@ComponentScans(value = 
        {@ComponentScan(value = "io.mieux.controller"),
        @ComponentScan(value = "io.mieux.service")})
@Configuration
public class BeanConfig {

}

@Import和@ImportResource

@Import:用来导入其他配置类。@Import(value = BookConfiguration.class)
@ImportResource:用来加载xml配置文件。

@SpringBootApplication
@EnableSwagger2
@ImportResource({"classpath*:applicationContext.xml"})
public class ProductApplication {

   public static void main(String[] args) {
      SpringApplication.run(ProductApplication.class, args);
   }
}

@Value

为了简化从properties里取配置,可以使用@Value, 可以properties文件中的配置值。

@Value(“${wx_appid}”)
public String appid;

@Autowired (属业spring的)

  1. @Autowired它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 
  2. @Autowired默认先按byType,如果发现找到多个bean,则,又按照byName方式比对,如果还有多个,则报出异常。可以手动指定按byName方式注入,使用@Qualifier。
  3. @Autowired 可以打在XXX[] 、List<XXX>上 ,此时会将容器中所有XXX类型的bean 都注入进去、且属性名没有约束,但是注意可以通过@Qualifier指定注入指定beanName的bean,属性名(变量名)是没有约束作用的
  4. @Autowired可以打在Map<String,XXX>上,此时所有XXX类型的bean都会被注入 ,beanName 为key ,对象为value,但是注意可以通过@Qualifier指定注入指定beanName的bean,属性名(变量名)是没有约束作用的

 

required属性

required属性值可以为true( 默认值)和false。如果为true的话,没有匹配的类则抛出异常;如果为false,则表示不是强制必须能够找到相应的类,无论是否注入成功,都不会抛错

@Autowired 注解接口

1.一个接口只有一个实现的情况下,属性名字怎么写都无所谓,因为按照类型匹配就只有一个bean
2.一个接口多个实现的情况下:
    ① 属性名字跟组件名字一致,组件名字可以在声明的时候指定,比如 @Service("abc")
    ② 属性名字跟组件名字不一致,配合@Qualifier 注解指定组件名字。

@Service("abc")
public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello() {
        System.out.println("say hello impl");
    }
}
@Controller
public class HelloController {
    @Autowired
    private HelloService abc;
    
    public void hello() {
        abc.sayHello();
    }
}

@Resource(这个注解属于J2EE的)

@Resource装配顺序
  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(baseDao)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

@Resource(name="baseDao",type="baseDaoImpl")
private BaseDao baseDao;

@PostConstruct 和 @PreDestory 

实现初始化和销毁bean之前进行的操作,只能有一个方法可以用此注释进行注释,方法不能有参数,返回值必需是void,方法需要是非静态的。

public class TestService {   
  
    @PostConstruct    
    public void  init(){    
        System.out.println(“初始化”);    
    }    
        
    @PreDestroy    
    public void  dostory(){    
        System.out.println(“销毁”);    
    }    
}  

3、请求映射

我们根据他们处理的Request的不同内容部分分为四类:(主要讲解常用类型)
A、处理request uri 部分(这里指uri template中variable,不含queryString部分)的注解:   @PathVariable;
B、处理request header部分的注解:@RequestHeader, @CookieValue;
C、处理request body部分的注解:@RequestParam,  @RequestBody;
D、处理attribute类型是注解: @SessionAttributes, @ModelAttribute;

@RequestMapping

用来处理请求地址映射的注解(将请求映射到对应的控制器方法中),可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

RequestMapping的属性

value:指定请求的实际url
(1)普通的具体值。如前面的value="/book"。
(2)含某变量的一类值。@RequestMapping(value="/get/{bookId}")
(3)ant风格
@RequestMapping(value="/get/id?"):可匹配“/get/id1”或“/get/ida”,但不匹配“/get/id”或“/get/idaa”;
@RequestMapping(value="/get/id*"):可匹配“/get/idabc”或“/get/id”,但不匹配“/get/idabc/abc”;
@RequestMapping(value="/get/id/*"):可匹配“/get/id/abc”,但不匹配“/get/idabc”;
@RequestMapping(value="/get/id/**/{id}"):可匹配“/get/id/abc/abc/123”或“/get/id/123”,也就是Ant风格和URI模板变量风格可混用。
(4)含正则表达式的一类值
@RequestMapping(value="/get/{idPre:\\d+}-{idNum:\\d+}"):可以匹配“/get/123-1”,但不能匹配“/get/abc-1”,这样可以设计更加严格的规则。可以通过@PathVariable 注解提取路径中的变量(idPre,idNum)
(5)或关系
@RequestMapping(value={"/get","/fetch"} )即 /get或/fetch都会映射到该方法上。
method:指定请求的method类型, GET、POST、PUT、DELETE等;
@RequestMapping(value="/get/{bookid}",method={RequestMethod.GET,RequestMethod.POST})
params:指定request中必须包含某些参数值是,才让该方法处理。
@RequestMapping(params="action=del"),请求参数包含“action=del”,如:http://localhost:8080/book?action=del
params=”userId”:请求参数中必须带有userId
params=”!userId”:请求参数中不能包含userId
params=”userId=1”:请求参数中userId必须为1
params=”userId!=1”:请求参数中userId必须不为1,参数中可以不包含userId
params={“userId”, ”name”}:请求参数中必须有userId,name参数
headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。
@RequestMapping(value="/header/id", headers = "Accept=application/json"):表示请求的URL必须为“/header/id 且请求头中必须有“Accept =application/json”参数即可匹配。

@PathVariable

用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数。

@RequestMapping(value="/user/{userId}/roles/{roleId}",method = RequestMethod.GET)  
public String getLogin(@PathVariable("userId") String userId,  
         @PathVariable("roleId") String roleId){  }

@RequestParam

@RequestParam用于将请求参数区数据映射到功能处理方法的参数上。

@RequestParam三个参数

value:参数名字,即入参的请求参数名字,如username表示请求的参数区中的名字为username的参数的值将传入;
required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将抛出异常;
defaultValue:默认值,表示如果请求中没有同名参数时的默认值,设置该参数时,自动将required设为false。

//如/requestparam1?username=zhang
public String requestparam4(@RequestParam(value="username",required=false) String username)
/*
区别: 
第一种写法参数为非必传,第二种写法参数为必传。参数名为userId。
第二种写法可以通过@RequestParam(required = false)设置为非必传。因为required值默认是true,所以默认必传。
第二种写法可以通过@RequestParam("userId")或者@RequestParam(value = "userId")指定参数名。
第二种写法可以通过@RequestParam(defaultValue = "0")指定参数默认值
*/

@RequestMapping("/list")
public String test(int userId) {
  return "list";
}
@RequestMapping("/list")
public String test(@RequestParam int userId) {
  return "list";
}

@CookieValue

@CookieValue 可以把Request header中关于cookie的值绑定到方法的参数上。

@RequestMapping("/displayHeaderInfo.do")  
public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie)  {  
} 

@RequestBody

作用: 

 i) 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
 ii) 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。

使用时机:

A) GET、POST方式提时, 根据request header Content-Type的值来判断:
application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据@RequestParam, @ModelAttribute也可以处理,当然@RequestBody也能处理);
multipart/form-data, 不能处理(即使用@RequestBody不能处理这种格式的数据);
其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用@RequestBody来处理);
 B) PUT方式提交时, 根据request header Content-Type的值来判断:
application/x-www-form-urlencoded, 必须;
multipart/form-data, 不能处理;
其他格式, 必须;
说明:request的body部分的数据编码格式由header部分的Content-Type指定;

@RequestMapping(value="/addUserInfo",method=RequestMethod.POST)
@ResponseBody
 //将请求中的data写入UserModel对象中
public String addUserInfo(@RequestBody UserModel user){
    System.out.println("user_name--------"+user.getUser_name());
    System.out.println("user_sex--------"+user.getUser_sex());
    System.out.println("user_age--------"+user.getUser_age());
    System.out.println("user_email--------"+user.getUser_email());
    //不会被解析为跳转路径,而是直接写入HTTP response body中
    return "{}";
}

@ResponseBody

作用: 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
使用时机: 返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;

//uri/login?name=use&password=********
@RequestMapping("/login")
@ResponseBody
public Object login(String name, String password, HttpSession session) {
	user = userService.checkLogin(name, password);
	session.setAttribute("user", user);
	return new JsonResult(user);
}

重定向和转发


@Controller
@RequestMapping("/hello")
public class ParamController {  
    @RequestMapping(value = "/test14")
    public String testForward(){
        return "forward:/hello/test16?id=1&type=forward";
    }
    @RequestMapping(value = "/test15")
    public String testRedirect(){
        return "redirect:test16?id=2&type=redirect";
    }
    @RequestMapping(value = "/test16")
    public String testForword(Model model,@RequestParam("id")Long id,@RequestParam("type") String type){
        model.addAttribute("msg","转发or重定向:"+type);
        return "demo";
    }
 
}

@SessionAttributes

如果多个请求之间需要共享数据,就可以使用@SessionAttribute。在控制器类上标注@SessionAttribute。

使用方法:
@SessionAttribute中,value指定需要放入会话的属性名称。type指定需要放入会话的属性类型。
@SessionAttributes(types=User.class)会将model中所有类型为 User的属性添加到会话中。
@SessionAttributes(value={“user1”, “user2”}) 会将model中属性名为user1和user2的属性添加到会话中。
@SessionAttributes(types={User.class, Dept.class}) 会将model中所有类型为 User和Dept的属性添加到会话中。
@SessionAttributes(value={“user1”,“user2”},types={Dept.class})会将model中属性名为user1和user2以及类型为Dept的属性添加到会话中。

@SessionAttributes(value={"user"})
@Controller
public class UserController {
 
    @RequestMapping("/testSessionAttributes")
    public String testSessionAttributes(Model model){
        User user = new User("jack","123456");
        model.addAttribute("user", user);
        return "success";
    }
} 

@ModelAttribute

主要的作用:将数据添加到model对象中,用于视图页面展示的时候使用。@ModelAttribute注解的方法,在controller中每个处理方法被调用之前,都会按照先后顺序被执行一次。因此,当一个controller映射多个URL,使用该注解需要谨慎。

(1)  @ModelAttribute 注释没有返回值的方法:

@Controller
@RequestMapping(value="/")
public class TestModelAttributeController {
     
    @RequestMapping(value="/result")
    public String login(Model model) {
        //如果测试成功,控制台输出true
        System.out.println(model.containsAttribute("username"));
        System.out.println(model.containsAttribute("pwd"));
        return "result";
    }
    @ModelAttribute
    public void user(
            @RequestParam("username") String username,
            @RequestParam("pwd") String pwd,Model model) {
         model.addAttribute("username", username);
         model.addAttribute("pwd", pwd);
    }
} 

(2) @ModelAttribute 注释返回具体类的方法

/*
这里,model属性的名称没有指定。
由返回类型隐含表示。
属性名称是user。
*/
@ModelAttribute
public User userModel(@RequestParam("username") String username,@RequestParam("pwd") String pwd){
    User  user = new User(username,pwd);
    return user;
}

(3)@ModelAttribute(value="")注释返回具体类的方法

@Controller
@RequestMapping(value="/")
public class TestModelAttributeController{
     
    @RequestMapping(value="result")
    public String login(Model model) {
        model.containsAttribute("username");
        return "result";
    }
    /*
    * 返回的是username的值
    *相当于model.addAttribute("username", username);
    */
    @ModelAttribute(value="username")
    public String userModel(@RequestParam("username") String username) {
        return username;
    }
}

(4)@ModelAttribute和@RequestMapping同时注释一个方法

/*
@ModelAttribute(“xxx”)的属性值作为model的attributeName,login方法返回值作为attributeName的属性值;
RequestMapping("/yyy")作为请求路径,也同时作为视图名,即跳转页面的名称
*/
@Controller
@RequestMapping(value="/")
public class TestModelAttributeController{
     
    @ModelAttribute("username")
    @RequestMapping(value="/result")
    public String login(@RequestParam("username") String username,Model model) {
         
        System.out.println(model.containsAttribute("username"));
        return username;   
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值