学习校园项目时记录的笔记(关于注解)

技术:
sprngboot框架,freemark模板插件,不再用前段框架页面模板,持久层使用jpa

springboot的特性:所有东西都能用注解解决,基于注解来完成。
springboot,会自动检查classpath:/resources目录
1.当前目录
2.当前没有了的config及子目录
上述目录中的application.properties/application.yml
-----在控制器参数中使用@Value可以在配置文件中读取属性
@Value(“ s p r i n g . d a t a s o u r c e . d r i v e r − c l a s s − n a m e " ) p r i v a t e S t r i n g d a t a s o u r c e ; @ R e q u e s t M a p p i n g ( " / d a t a " ) p u b l i c S t r i n g d a t a ( @ V a l u e ( " {spring.datasource.driver-class-name}") private String datasource; @RequestMapping("/data") public String data(@Value(" spring.datasource.driverclassname")privateStringdatasource;@RequestMapping("/data")publicStringdata(@Value("{spring.datasource.driver-class-name}”) String name, HttpServletRequest request){

@ConfigurationProperties(prefix = “school”)//配置属性注解
可以扫描配置文件里面的属性,通常用于扫描多个属性,对象
单个属性使用@value获取配置文件的属性值
但是这个属性只能扫描,application.properties的属性,或者application.yml的属性
如果需要加载其他配置属性就需要加入@PropertySource(value = {“classpath:site.properties”})
@Component
@ConfigurationProperties(prefix = “ylrc.site”)
@PropertySource(value = {“classpath:site.properties”})

List 集合中的对象按照一定的顺序排放,里面的内容可以重复。
List接口实现的类:ArrayList(实现动态数组), Vector(实现动态数组) ,
LinkedList(实现链表), Stack(实现堆栈)

使用jpa报错
Error creating bean with name ‘entityManagerFactory’ defined in class path resource
@Id包报错
jpa的包都是javax.persistence.*

 配置JpaBaseConfiguration.java:234- spring.jpa.打开-默认情况下,“视图中”处于启用状态。

因此,可以在视图呈现期间执行数据库查询。显式配置spring.jpa.打开-以禁用此警告

spring.jpa.open-in-view=false解决

jpa在实体中有但是数据库没有的时候回新增
jpa在实体中没有但是数据库有的时候,不会帮你把表的字段删除。
ctrl+shift+o清理包
我们开发一般会将代码从简,对于重复使用的可以抽取出来
抽取公共的实体,并加上注解 * 公共的基础实体类
*/
@MappedSuperclass
让其他实体类继承这个实体

@MappedSuperclass的用法
用在实体的继承过程中的父类上;
如果不用@MappedSuperclass 而用@Entity替换的话,只会生成一张cat表,
字段有:id,name,shanghaicat,bejingcat

@MappedSuperclass 用在父类上面。当这个类肯定是父类时,加此标注。如果改成@Entity,
则继承后,多个类继承,只会生成一个表,而不是多个继承,生成多个表

dao文件:
声明 UserRepository接口,继承JpaRepository,如下所示
public interface UserRepository extends JpaRepository<User, Long> {

}

这里的 JpaRepository继承了接口PagingAndSortingRepository和QueryByExampleExecutor。而
,PagingAndSortingRepository又继承CrudRepository。
因此,JpaRepository接口同时拥有了基本CRUD功能以及分页功能。因此
,这里我们可以继承JpaRepository,从而获得Spring为我们预先定义的多种基本数据操作方法。

html
required属性
带有必填字段的 HTML 表单:

单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。
通过单例模式可以保证系统中,
应用该模式的类一个类只有一个实例。即一个类只有一个对象实例,

可是我认为这不是使用单例模式的理由。我认为使用单例模式的时机是当实例存在多个会引起程序逻辑错误的时候。比如类似有序的号码生成器这样的东西,怎么可以允许一个应用上存在多个呢?

Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。

一般Singleton模式通常有三种形式:

第一种形式:懒汉式,也是常用的形式。

第二种形式:饿汉式

第三种形式: 双重锁的形式。

–通常将构造函数私有化,只能在本类中调用,其他方法想调用,只能调用类里面的静态方法

org.apache.commons commons-lang3 commons-codec commons-codec

加入这两个依赖后可以使用apache给的判断空的方法,先会去判断是否null,然后判断是否是“”

自定义注解:

字段注解一般是用于校验字段是否满足要求,hibernate-validate依赖就提供了很多校验注解 ,如@NotNull、@Range等,但是这些注解并不是能够满足所有业务场景的。

比如我们希望传入的参数在指定的String集合中,那么已有的注解就不能满足需求了,需要自己实现。
自定义注解
定义一个@Check注解,通过@interface声明一个注解

@Target({ ElementType.FIELD}) //只允许用在类的字段上
@Retention(RetentionPolicy.RUNTIME) //注解保留在程序运行期间,此时可以通过反射获得定义在某个类上的所有注解
@Constraint(validatedBy = ParamConstraintValidated.class)
public @interface Check {
/**
* 合法的参数值
* */
String[] paramValues();

/**
 * 提示信息
 * */
String message() default "参数不为指定值";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

}

@Target 定义注解的使用位置,用来说明该注解可以被声明在那些元素之前。

ElementType.TYPE:说明该注解只能被声明在一个类前。

ElementType.FIELD:说明该注解只能被声明在一个类的字段前。

ElementType.METHOD:说明该注解只能被声明在一个类的方法前。

ElementType.PARAMETER:说明该注解只能被声明在一个方法参数前。

ElementType.CONSTRUCTOR:说明该注解只能声明在一个类的构造方法前。

ElementType.LOCAL_VARIABLE:说明该注解只能声明在一个局部变量前。

ElementType.ANNOTATION_TYPE:说明该注解只能声明在一个注解类型前。

ElementType.PACKAGE:说明该注解只能声明在一个包名前

@Constraint 通过使用validatedBy来指定与注解关联的验证器

@Retention 用来说明该注解类的生命周期。

RetentionPolicy.SOURCE: 注解只保留在源文件中 源文件

RetentionPolicy.CLASS : 注解保留在class文件中,在加载到JVM虚拟机时丢弃 编译

RetentionPolicy.RUNTIME: 注解保留在程序运行期间,此时可以通过反射获得定义在某个类上的所有注解。

1.创建一个自定义注解
**

  • 实体检验自定义注解类

  • @author 李
    */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ValidateEntity {

    public boolean required() default false;//是否检验null

    public boolean requiredLeng() default false;//是否检验长度

    public int maxLength() default -1;//最大长度

    public int minLength() default -1;//最小长度

    public String errorRequiredMsg() default “”;//值为null时的错误提示信息

    public String errorMinLengthMsg() default “”;//最小长度不满足时的提示信息

    public String errorMaxLengthMsg() default “”;//最大长度不满足时的提示信息

}
2.编写实体类验证工具类
/**

  • 验证实体工具类

  • @author 李
    */
    public class ValidateEntityUtil {

    public static JsonResult validate(Object object) {
    Field[] declaredFields = object.getClass().getDeclaredFields();
    for (Field field : declaredFields) {
    ValidateEntity annotation = field.getAnnotation(ValidateEntity.class);
    if (annotation != null) {
    if (annotation.required()) {
    //表示该字段是必填字段
    field.setAccessible(true);
    try {
    Object o = field.get(object);
    //首先判断是否为空
    if (StringUtils.isEmpty(o)) {
    JsonResult jsonResult = JsonResult.CUSTOM_ERROR;
    jsonResult.setMsg(annotation.errorRequiredMsg());
    return jsonResult;
    }
    //到这,说明该变量的值不是null
    //首先判断是不是String类型
    if (o instanceof String) {
    //若是字符串类型,则检查其长度
    if (annotation.requiredLeng()) {
    if (o.toString().length() < annotation.minLength()) {
    JsonResult jsonResult = JsonResult.CUSTOM_ERROR;
    jsonResult.setMsg(annotation.errorMinLengthMsg());
    return jsonResult;
    }
    if (o.toString().length() > annotation.maxLength()) {
    JsonResult jsonResult = JsonResult.CUSTOM_ERROR;
    jsonResult.setMsg(annotation.errorMaxLengthMsg());
    return jsonResult;
    }
    }
    }
    } catch (IllegalArgumentException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    }
    return JsonResult.SUCCESS;
    }

}
3.实体类使用方式
@ValidateEntity(required = true,requiredLeng = true,errorRequiredMsg=“不能为空”,maxLength = 10,errorMaxLengthMsg = “超过限制10个字”)
private String content;

private Long accountId;
@ValidateEntity(required = true,requiredLeng = true,errorRequiredMsg="不能为空",maxLength = 30,errorMaxLengthMsg = "超过限制30个字")
private String title;

4.编写接口测试
@RequestMapping(“test”)
JsonResult test(Problem problem){
System.out.println(problem.getContent().length());
System.out.println(problem.getTitle().length());
JsonResult validate = ValidateEntityUtil.validate(problem);
if (validate.getCode()!=1)return validate;
return JsonResult.success(problem);
}
5.测试


String[] value();
看似是一个无参方法,实际上是一个成员变量,一个属性
如果注解上只有一个属性,name这个属性最好叫做value,这是约定俗成的,
在方法上使用这个注解
@myannotation(value=” “)
如果是value那么可以省略不写
在属性后面加上default设置了默认的值了,那么使用的使用可以无须传值。
如果注解内部没有定义参数可以叫做标记
如果内部定义了配置参数,那么可以叫做元数据。
元注解的使用:
元注解是用于修饰其他注解的注解
hdk5.0提供; 四种元主角:
retention,Target,Documented,Inheriteed。
@Retention:
用于修饰注解,用于指定修饰的那个注解的生命周期,@Retention傲寒一个RententionPolicy
保留,保留政策。
@Retention使用时必须为value成员变量指定值
RetionPolicy.SOURCE在源文件中有效,即源文件保留,编译器直接丢弃这种策略的注释,在class文件中不会白柳注解信息
RetionPolicy.CLASS,在class文件中有效(即CLASS保留),保留在class文件中,但是当运行java程序时,他就不会继续加载了,不会保存在内存中,
JVM不会保留注解,如果没有加Retention元注解,那么相当于默认的注解就是这种状态。
Retention.RUNTIME,在运行时有效(即运行时保留)在运行java程序时,JVM会保留注释,加载到内存中,那么程序就可以通过反射获取该注释。

@Target
目标,value里面是一个枚举类型,默认是全部都可以

ElementType.TYPE:说明该注解只能被声明在一个类前。

ElementType.FIELD:说明该注解只能被声明在一个类的字段前。

ElementType.METHOD:说明该注解只能被声明在一个类的方法前。

ElementType.PARAMETER:说明该注解只能被声明在一个方法参数前。

ElementType.CONSTRUCTOR:说明该注解只能声明在一个类的构造方法前。

ElementType.LOCAL_VARIABLE:说明该注解只能声明在一个局部变量前。

ElementType.ANNOTATION_TYPE:说明该注解只能声明在一个注解类型前。

ElementType.PACKAGE:说明该注解只能声明在一个包名前

@Documented
用于指定被该元注解修饰的注解类被javadoc工具提取成文档,默认情况下是不包括注解的,但是加了这个注解生成的文档中就会带着注解了
@Inherited修饰的Annotation,则其子类将自动具有该注解
被它修饰的Annotation将具有几成新。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值