Spring注解深究

昨天看阿里的java开发手册,其中有一个OOP规约(网上百度了一下,这个规约是阿里自己制定的),其中有一条: 外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加 @Deprecated 注解,并清晰地说明采用的新接口或新服务是什么。 这其中提到了 @Deprecated 注解,在之前的开发过程中没遇到过这个注解,于是查了下他的功能: 简单来讲就是,若某类或某方法加上该注解之后,表示此方法或类不再建议使用,调用时也会出现删除线,但并不代表不能用,只是说,不推荐使用,因为还有更好的方法可以调用。 或许有人会问 为什么会出现加这个注解呢,直接在写方法的时候定义一个新的不就好了吗? 因为在一个项目中,工程比较大,代码比较多,而在后续开发过程中,可能之前的某个方法实现的并不是很合理,这个时候就要新加一个方法,而之前的方法又不能随便删除,因为可能在别的地方有调用它,所以加上这个注解,就方便以后开发人员的方法调用了。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.renrenche.rest.protocol;
public class Response<T> {
    private int version = 0;
    private int status = 0;
    private String errMsg = "";
    /** @deprecated */
    @Deprecated
    private String errorMsg = "";
    private long ts = System.currentTimeMillis();
    private T data;
    public Response() {
    }
    public static <T> ResponseBuilder<T> builder() {
        return new ResponseBuilder();
    }
    public static <T> Response<T> ok() {
        return ok((Object)null);
    }
    public static <T> Response<T> ok(T data) {
        return ok(0, data);
    }
    public static <T> Response<T> ok(int version, T data) {
        return ok(version, System.currentTimeMillis(), data);
    }
    public static <T> Response<T> ok(int version, long ts, T data) {
        return of(ErrorCode.OK, version, ts, "ok", data);
    }
    public void setErrorCode(ErrorCode code) {
        this.setErrorCode(code, code.getMsg());
    }
    public void setErrorCode(ErrorCode code, String msg) {
        if (null != code) {
            this.status = code.getCode();
            this.errMsg = msg;
            this.errorMsg = msg;
        }
    }
    public static <T> Response<T> error(ErrorCode code) {
        return of(code, code.getMsg());
    }
    public static <T> Response<T> error(ErrorCode code, T data) {
        return of(code, (String)null, data);
    }
    public static Response<String> error(String data, ErrorCode code) {
        return of(code, (String)null, data);
    }
    public static <T> Response<T> error(ErrorCode code, String msg) {
        return of(code, msg, (Object)null);
    }
    public static <T> Response<T> error(ErrorCode code, String msg, T data) {
        return of(code, 0, msg, data);
    }
    public static <T> Response<T> error(ErrorCode code, int version, String msg, T data) {
        return of(code, version, System.currentTimeMillis(), msg, data);
    }
    public static <T> Response<T> error(ErrorCode code, int version, long ts, String msg, T data) {
        return of(code, version, ts, msg, data);
    }
    public static <T> Response<T> of(ErrorCode code) {
        return of(code, code.getMsg());
    }
    public static <T> Response<T> of(ErrorCode code, T data) {
        return of(code, (String)null, data);
    }
    public static Response<String> of(String data, ErrorCode code) {
        return of(code, (String)null, data);
    }
    public static <T> Response<T> of(ErrorCode code, String msg) {
        return of(code, msg, (Object)null);
    }
    public static <T> Response<T> of(ErrorCode code, String msg, T data) {
        return of(code, 0, msg, data);
    }
    public static <T> Response<T> of(ErrorCode code, int version, String msg, T data) {
        return of(code, version, System.currentTimeMillis(), msg, data);
    }
    public static <T> Response<T> of(ErrorCode code, int version, long ts, String msg, T data) {
        Response<T> resp = new Response();
        resp.setErrorCode(code);
        resp.setData(data);
        if (null != msg) {
            resp.setErrMsg(msg);
        }
        resp.setVersion(version);
        resp.setTs(ts);
        return resp;
    }
    public int getStatus() {
        return this.status;
    }
    public void setStatus(int status) {
        this.status = status;
    }
    public String getErrMsg() {
        return this.errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
        this.errorMsg = errMsg;
    }
    public T getData() {
        return this.data;
    }
    public void setData(T data) {
        this.data = data;
    }
    /** @deprecated */
    @Deprecated
    public String getErrorMsg() {
        return this.errorMsg;
    }
    /** @deprecated */
    @Deprecated
    public void setErrorMsg(String errorMsg) {
        this.errMsg = errorMsg;
        this.errorMsg = errorMsg;
    }
    public int getVersion() {
        return this.version;
    }
    public void setVersion(int version) {
        this.version = version;
    }
    public long getTs() {
        return this.ts;
    }
    public void setTs(long ts) {
        this.ts = ts;
    }
    public String toString() {
        return "Response{version=" + this.version + ", status=" + this.status + ", errMsg='" + this.errMsg + '\'' + ", errorMsg='" + this.errorMsg + '\'' + ", ts=" + this.ts + ", data=" + this.data + '}';
    }
}

**spring MVC注解深入研究 @Controller @Service @Controller和 @Component
注册一个action 到spring 上下文中,bean 的ID 默认为类名称开头字母小写。
@Repository、@Service 和@Controller。这 3 个注解和 @Component 是等效的,但是从注解类的命名上,很容易看出这 3 个注解分别和持久层、业务层和控制层(Web 层)相对应。虽然目前这 3 个注解和 @Component 相比没有什么新意,但 Spring 将在以后的版本中为它们添加特殊的功能。所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用@Repository、@Service 和 @Controller 对分层中的类进行注解,而用 @Component 对那些比较中立的类进行注解。 例:@Controller
public class Apple extends Friut {} @Autowired
以byType的方式对类成员变量、方法及构造函数进行标注,完成自动装配的工作。Spring 将直接采用 Java 反射机制对 类 中的 私有成员变量进行自动注入。所以对成员变量使用 @Autowired 后,可将它们的getter和setter 方法删除。
例:

public class Boss { 
@Autowired 
private Car car; 
@Autowired 
private Office office; 
} 也可以对set方法和构造函数使用@ Autowired注解 ,等同于上文public class Boss { 
  private Car car; 
  private Office office; 
  @Autowired 
  public void setCar(Car car) { 
    this.car = car; 
  } 
  @Autowired 
  public void setOffice(Office office) { 
    this.office = office; 
  } 
}
public class Boss { 
  private Car car; 
  private Office office; 
  @Autowired 
  public Boss(Car car ,Office office){ 
    this.car = car; 
    this.office = office ; 
  } 
} 

如何使用Autowired 的required参数 @Autowired(required = false)
public void setOffice(Office office) {
  this.office = office;
}一般情况下,使用 @Autowired 的地方都是需要注入 Bean 的,使用了自动注入而又允许不注入的情况一般仅会在开发期或测试期碰到(如为了快速启动 Spring 容器,仅引入一些模块的 Spring 配置文件),所以 @Autowired(required = false) 会很少用到。 @Resource
@Resource 的作用相当于 @Autowired,只不过 @Autowired 按 byType 自动注入,而 @Resource 默认按 byName 自动注入。@Resource 有两个属性是比较重要的,分别是 name 和 type,Spring 将 @Resource 注解的 name 属性解析为 Bean 的名字,而 type 属性则解析为 Bean 的类型。所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略。
例:

public class Boss { 
  // 自动注入类型为 Car 的 Bean 
  @Resource 
  private Car car; 
  // 自动注入 bean 名称为 office 的 Bean 
  @Resource(name = "office") 
  private Office office; 
} @PostConstruct 和 @PreDestroy
只需要在方法前标注 @PostConstruct 或 @PreDestroy,这些方法就会在 Bean 初始化后或销毁之前被 Spring 容器执行, 常用于对静态变量的处理。public class Boss { 
  private static Car car = initCar(); 
  @Resource(name = "office") 
  private Office office; 
  @PostConstruct 
  public void initCar(){ 
    System.out.println("postConstruct1"); 
  } 
  @PreDestroy 
  public void preDestroy1(){ 
    System.out.println("preDestroy1"); 
  } 
} @RequestMapping
将URL映射到类或方法上。@RequestMapping(value="/car")
public class Car { 
  @RequestMapping(value="/getName")
  public String myCarName(){
    return “audi”;
  }
} 

通过http://{ ip:port/上下文}/car/getName 来请求该方法当它定义在类级别时,标明该控制器处理所有的请求都被映射到 /car路径下。@RequestMapping中可以使用 method 属性标记其所接受的方法类型,如果不指定方法类型的话,可以使用 HTTP GET/POST 方法请求数据,但是一旦指定方法类型,就只能使用该类型获取数据。支持方法共有四种:GET, POST, PUT, DELETE

@RequestMapping(value="/getName", method = RequestMethod.GET)
public String getName(String userName) {
  return userName;
} 绑定 @RequestMapping参数
使用 @PathVariable 注解方法参数并将其绑定到URI模板变量的值上@RequestMapping(value="/departments/{departmentId}/employees/{employeeId}") 
public String findEmployee( @PathVariable String departmentId, 
                 @PathVariable String employeeId){ 
  System.out.println("Find employee with ID: " + employeeId + 
  " from department: " + departmentId); 
  return "someResult"; 
} 支持正则表达式@RequestMapping(value="/{textualPart:[a-z-]+}.{numericPart:[\\d]+}") 
public String regularExpression( @PathVariable String textualPart, 
                    @PathVariable String numericPart){ 
  System.out.println("Textual part: " + textualPart + ", numeric part: " + numericPart); 
  return "someResult"; 
} @RequestParam 
可以把请求参数传递给请求方法
例:  http://{ ip:port/上下文}/car/getName?ownerId=5@RequestMapping(value="/car")
public class Car { 
  @RequestMapping(value="/getName")
  public String myCarName(@RequestParam("ownerId") int ownerId){
    return “audi”;
  }
} @ModelAttribute

@ModelAttribute有三种用法:
1、注解方法
当它作用在方法上时,标明该方法的目的是添加一个或多个模型属性(model attributes)。该方法支持与@RequestMapping一样的参数类型,但并不能直接映射成请求。controller中的@ModelAttribute方法会在所有@RequestMapping方法调用之前而调用,因此要小心使用。利用这个特征进行权限验证, index方法执行之前会先执行preRun方法@Controller
@RequestMapping(value="/test")
public class PassportController {
  @ModelAttribute
  public void preRun() {
    if(user != “admin”){
      throw Exception(“没有权限”);
    }
  }
  @RequestMapping(method=RequestMethod.GET)
  public String index() {
    return “login/index”;
  }
}2、注解方法中的入参
用于将多个请求参数绑定到一个命令对象,将这个对象添加到request作用域,从而简化绑定流程,而且自动暴露为模型数据用于jsp展示时使用@RequestMapping(value=“test”)
public String test(@ModelAttribute(“user”) UserModel user){
  User.setName(“aaa”);
}此时可以在视图页面使用 u s e r . n a m e 来 获 取 绑 定 的 命 令 对 象 的 属 性 3 、 注 解 方 法 的 返 回 值 , 效 果 同 上 , 将 返 回 值 添 加 到 r e q u e s t 作 用 域 , j s p 页 面 中 可 以 通 过 {user.name}来获取绑定的命令对象的属性 3、注解方法的返回值,效果同上,将返回值添加到request作用域,jsp页面中可以通过 user.name3requestjsp{user.name}的方式直接调用,@ModelAttribute 注解的返回值会覆盖@RequestMapping 注解方法中的@ModelAttribute 注解的同名命令对象。public @ModelAttribute(“user2”) UserModel test3(@ModelAttribute(“user2”) UserModel user) @RequestBody
读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上 ,再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。 @ResponseBody
将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。 @ExceptionHandler和@ControllerAdvice
@ExceptionHandler 注解到方法上,出现异常时会执行该方法。 @ControllerAdvice 使一个Contoller成为全局的异常处理类,类中用@ExceptionHandler方法注解的方法可以处理所有Controller发生的异常。 @RestController (spring 3.1 以上)
使一个类以Rest风格返回请求数据, 它与@Controller的差别在于使用@Controller标注的类别最后会回传一个String,然后透过viewResolver组装出完整的view page路径后将这个view呈现在前端页面中。而使用 @RestController标注表示此类别最后会回传一个POJO对象而非一个页面,因此也不需要透过viewResolver来帮忙组装回传值。
通过jackson套件,可以将RestController回传的domain对象以JSON或XML格式的方式返回前端。

@RestController
public class HelloWorldRestController {
   
   @RequestMapping("/hello/{player}")
   public Message message(@PathVariable String player) {
        Message msg = new Message(player, "Hello, " + player);
     return msg;
   }
} VO字段验证

@AssertFalse

验证的数据类型 :Boolean,boolean
说明 :验证注解的元素值是false

@AssertTrue

验证的数据类型 :Boolean,boolean

说明 :验证注解的元素值是true @NotNull

验证的数据类型 :任意类型
说明 :验证注解的元素值不是null

@Null

验证的数据类型 :任意类型
说明 :验证注解的元素值是null

@Min(value=值)

验证的数据类型 :BigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存储的是数字)子类型
说明 :验证注解的元素值大于等于@Min指定的value值

@Max(value=值)

验证的数据类型 :和@Min要求一样
说明 :验证注解的元素值小于等于@Max指定的value值

@DecimalMin(value=值)

验证的数据类型 :和@Min要求一样
说明 :验证注解的元素值大于等于@ DecimalMin指定的value值

@DecimalMax(value=值)

验证的数据类型 :和@Min要求一样
说明 :验证注解的元素值小于等于@ DecimalMax指定的value值

@Digits(integer=整数位数, fraction=小数位数)

验证的数据类型 :和@Min要求一样
说明 :验证注解的元素值的整数位数和小数位数上限

@Size(min=下限, max=上限)

验证的数据类型 :字符串、Collection、Map、数组等
说明 :验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小

@Past

验证的数据类型 :java.util.Date,java.util.Calendar,Joda Time类库的日期类型
说明 :验证注解的元素值(日期类型)比当前时间早

@Future

验证的数据类型 :与@Past要求一样
说明 :验证注解的元素值(日期类型)比当前时间晚

@NotBlank

验证的数据类型 :CharSequence子类型
说明 :验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于

@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的首位空格

@Length(min=下限, max=上限)

验证的数据类型 : CharSequence子类型
说明 :验证注解的元素值长度在min和max区间内

@NotEmpty

验证的数据类型 :CharSequence子类型、Collection、Map、数组
说明 :验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)

@Range(min=最小值, max=最大值)

验证的数据类型 :BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型
说明 :验证注解的元素值在最小值和最大值之间

@Email(regexp=正则表达式,flag=标志的模式)

验证的数据类型 :CharSequence子类型(如String)
说明 :验证注解的元素值是Email,也可以通过regexp和flag指定自定义的email格式

@Pattern(regexp=正则表达式,flag=标志的模式)

验证的数据类型 :String,任何CharSequence的子类型
说明 :验证注解的元素值与指定的正则表达式匹配

@Valid

验证的数据类型 :任何非原子类型
说明 :指定递归验证关联的对象;如用户对象中有个地址对象属性,如果想在验证用户对象时一起验证地址对象的话,在地址对象上加@Valid注解即可级联验证****

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值