spring项目分层详解以及各分层中常用的注解

134 阅读6分钟

记录一下常见的注解,并进行一定的深入学习。

一.Lombok注解

  1. @Setter @Getter 为private变量创建set和get方法,getter可以用于枚举,但是setter不可以。
  2. @EqualsAndHashCode @ToString 重写equals,hashcode以及toString方法。
  3. @RequiredArgsConstructor 用于生成包含final@NonNull注解的成员变量的构造方法,推荐使用这种依赖注入的方式引入依赖。(Effective Java 第五条)。
  4. @AllArgsConstructor @NoArgsConstructor顾名思义,没什么值得拎出来说的,不过他们俩可以一起连用。
  5. @Data 包含上述的(除全参和无参构造), 若类中无final@NonNull,则生成无参构造。此外,可以加入staticConstructor=""来模拟静态工厂方式创立对象。(Effective Java 第一条)。
  6. @Builder 当参数过多时,可以使用此方法进行链式创建。builder().*****.build()即可创建。Builder和Data千万不要混用,会互相冲突!!!
  7. @Slf4j 用来创建日志。

二.Restful注解

Restful风格,就是一种面向资源服务的API设计方式,他不是规范,是一种设计模型。

2.1 类和方法上的注解

  1. @RestController@Controller的衍生,用于指定使用Restful风格的注解,作用在类上,相当于@Controller@ResponseBody的合体,此时该类中的所有方法只能返回String,Object与Json等实体对象,不能跳转模板页面。若非得跳转页面,也有方法,就用ModelAndView进行封装,如下:
@RestController
public class UserController {
 
    @GetMapping(value = "/page")
    public String toPage(){
        ModelAndView mv = new ModelAndView("page");
      	return mv;    
    }
}

如果页面上跳转的多的话,那就@Controller@ReponseBody分开使用。
2. @RequestMapping("/url")相当于一种路由映射,指明该类或方法的访问地址,可以作用在类上或者方法上。 3. @GetMapping("/url")一种典型的resful风格的注解,用于指定Get方式查询的方法,相当于@RequestMapping("/url", method=RequestMethod.GET)简写,后续不再赘述。 4. @PostMapping(), @DeleteMapping(), @PutMapping(), @PatchMapping()增删改,其中patch是对put的一种补充,put是更新的整体,patch是对局部的更新(这里我还没用过,其中细节有待增加)。

2.2 入参注解

  1. @PathVariable用于uri里的参数,通常和@GetMapping一起连用
@RequestMapping("/getUserById/{name}")
public User getUser(@PathVariable("name") String name){
    return userService.selectUser(name);
}

若形参名字一致,("name")可以省去,代码更为简洁,可读性也不差。
2. @RequestParam也是用于对GET方式请求的http中获取参数,不过他和@PathVariable有一定的区别,比如:

http://localhost:8080/springmvc/hello/101?param1=10&param2=20
@RequestMapping("/hello/{id}")  
public String getDetails(@PathVariable String id,  
    @RequestParam(value="param1", required=true) String param1,  
    @RequestParam(value="param2", required=false) String param2){  
.......  
}

区别一目了然。此外,其还可以指定是否必需,默认值等信息。@RequestParam(value = "id", required = false, defaultValue = "0")
3. @RequestBody可以用来处理application/xml或application/json数据,我只处理过json。当使用这个入参注解时,前端必须以@PostMapping方法来访问,其他也没啥好说的,都是较为简单的注解。 4. @ModelAttribute还没用过,等碰到了再来更新。

三.dao层常用的注解

dao(Data Access Object)是数据访问层,把访问数据库的代码封装起来,位于数据库与业务逻辑(Service)之间。人话就是,封装对数据库的访问:增删改查,不涉及业务逻辑,只是达到按某个条件获得指定数据的要求。值得注意的是,dao层全部是接口。

  1. @Mapper是Mybatis的注解,作用在dao层的接口上,相当于一个mapper.xml文件上,会为接口生成一个动态接口类。在dao层不可以有相同名字的接口,即不支持重载。因为mapper文件是通过id与接口进行对应的。
  2. @Repository@Mapper作用相同,但是Repository本身不起作用,只起个标识作用,若想这个接口真正被扫描,需要在启动类上加@MapperScan
  3. @MapperScan理论上可以代替所有的Mapper,但我建议还是加上,不光可以增加dao层的可读性,还可以有效滴避免出现各种幺蛾子。同时,只使用Mapper不使用Repository时,idea会不识别,autowiwred时会爆红,可以都加上。
  4. @Param该注解是为SQL语句中参数赋值而服务的,既可以传基本类型,也可以传对象,如:
//传基本类型
public User selectUser(@Param("userName") String name,@Param("password") String pwd);

//映射到xml中的<select>标签
<select id="selectUser" resultMap="User">
select * from user where user_name = #{userName} and user_password=#{password}
</select>

//传对象
public List<User> getAllUser(@Param("user") User u);

<select id="getAllUser" parameterType="com.vo.User" resultMap="userMapper">  
        select   
        from user t where 1=1  
        and   t.user_name = #{user.userName}  
        and   t.user_age = #{user.userAge}  keyi
</select> 

@Select等注解用的已经不多了,因此在这里不再介绍。不过,我觉得还是很有必要介绍一下BaseMapper这个接口的
自己写的Mapper接口,只需要继承了这个接口,只需要写方法名,结合@Param的使用,就可以做出增删改查的操作了。继承后写出的代码,简洁明了,可读性非常的强。同时,dao和entity(详情见4)一一对应,看着非常的爽。BaseMapper写了一些基本的增删改的语句,继承后可以直接使用。若要写一些复杂的SQL语句,也可以自己进行定义,按照他的格式进行书写即可。[可以这个大佬的,写的很好,入门足够了。](mybatis-plus入门学习-BaseMapper - 掘金 (juejin.cn))

四.dto层

DTO就是数据传输对象(Data Transfer Object)的缩写。 DTO模式,是指将数据封装成普通的JavaBeans,在J2EE多个层次之间传输。这个dto有点抽象,不同的人有着不同的理解,在这里也给出我个人的一点浅薄理解,若有不对之处,还请在评论区提出。 dto是做表示层的,即展示给用户看的。dto可以由多个实体构成,也可以是一个实体的一部分,十分的灵活。dto本身不是业务对象,他是根据前端需求进行设计的。一种主流的思想认为,通过dto可以实现表现层与entity层进行解耦合,表现层不引用entity层。如果开发过程中模型变了,而展示界面没变,只需改动entity即可,不需要改动表现层。简而言之,dto层就是为ui提供数据的。

4.1dto层中常用的注解

dto常用@Data、@NoArgsConstructor、@AllArgsConstructor连用,建立构造参数和set与get方法。 同时,里边的属性使用@ApiModelPropertyswagger注解对属性进行注释。同时,通常也接受Request方式进行传参构造,如:

public UserInfoDto(UserRequest req) {
    this.name = req.getNmae();
    ...
}

五.vo层

vo(value object)又是一个容易混淆的概念,许多人第一次接触时分不清他和dto的区别(俺也是。。)。其实挺好理解的,vo就是展示用的数据,不管展示方式是网页或是app。vo主要存在 形式就是js里面的对象(理解成json也没问题)。与dto相比,主要有两个不同:1.字段不一样,vo会根据需求删减一些字段; 2. 字段的值也不一样,vo会根据需求对dto的值进行处理,使其符合业务逻辑,比如:

//DTO:
{
    "name":"lih",
    "address":"南京",
    "monthSalary":"3000",
    "tel":"177****",
}

//vo
{
    "name":"lih",
    "monthSalary":2k~1w, //真惨
}

四.entity层

entity为实体层,用于存放我们的实体类,与数据库中的属性值基本保持一致,实现set和get