全栈之路-Springboot初试

前言

距离2018年结束还有15天,也是我正式步入开发行业的第三个年头,他们都说步入开始后悔,但是仔细想想其实这三年来还是挺好的,有枯燥乏味,有焦躁不安,有自暴自弃,还有在第二天早晨重新焕发坐上清晨的公交车奔向公司。
三年来的时光,先后换了4家公司,第一家公司呆了近2年,而后的更换公司却有些频繁,从重庆再到杭州,虽然我很不想这样,但是这个行业好像就那么如此。
第一年的工作是Android开发,让我对Android有了深入的了解,包括一些硬件基础摄像头,蓝牙,USB接口,还有音频合成等,也打下了不错的java基础。
第二年的工作主要倾向于web前端开发,公司业务逐步拓展,作为一线开发者的我开始学习前端,从html,css,js,再到jquery,vue,微信小程序,也为我打开了前端开发的知识大门。
第三年的工作是有些偏向于管理方向,开始带领公司小团队,同时也更换两家公司,这一年开始学习了javaweb的学习,从年初到年末,先后利用工作之余,学习了Servlet、Jsp、struts2,spring等,最后开始对spring全家桶着迷。
这一路走来,第一家公司跟着公司大佬学习,学会了对代码严谨,还有测试,如今始终还记老板时常对我的念叨(老板是技术出身的):敲代码是一件很神圣的事情,所以要对代码充满敬畏之心,所以修改代码必须细心再细心,提交代码要反复测试。那段时间让我知道了对测试的重要性,还有代码的严谨。我真的很感谢老板,收留了毕业后走投无路的我,也教会了很多知识。第二家公司,担任了公司项目经理,负责公司项目体系策划,开发团队管理,从需求分析到最后项目上线,也让我有了一把应聘别人的经验。所以我觉得开发并不是那么无聊,关键看做开发的人,大概我也是假的开发,不过经常被人吐槽万金油确实不好受。

开始

理论知识

javaweb后端开发,对于正式接触这个技术栈的时候,第一印象就是数据,每天所做就是与数据打交道,从简单上考虑,所有的后端开发无论java,php,pythan,还是其他的语言无非就是四种姿势:


  • 但是说起来就四个字,但是只要真正接触了后端开发后才发现,这四个字不简单。

增,我们要考虑几种业务模块场景:
1.直接增加一条数据(新增用户)
2.查询后增加指定字段(主要为更新字段)
3.新增表(数据新增表,与现有表相关联,列如:用户表,关联表就有用户登录信息表,会员表,权限表等)
4.新增字段(业务需求新增字段,不过最好前期架构好字段)
......
增加数据这业务模块,对于菜鸟而言估计就是要啥数据,就不断新增,于是就导致数据库臃肿,业务链繁琐,于是查询数据缓慢,最后后台服务器不堪重负崩了。

删,删除的业务场景同样比繁琐。
1.删除单条信息(常见为注销用户,一般产品这些不会作为直接删除业务)
2.删除多条信息(遍历删除,或则条件删除,常见为注销用户,删除他的所有关联信息)
......删除业务又同时依赖于查询业务模块

修改,也是更新,业务逻辑也是在后端业务中比较繁琐的一个部分
1.字段修改(例如更新用户登录状态,商品状态,订单状态)
2.多条记录修改(一般为分类常见,多数为一对多表,多对多表场景)
3.多表修改(查询多表修改,耗时很长,应该避免出现超过3个表同时修改场景,减少服务器负担)
.....

查询,是后端数据的重中之中,因为前端数据展示,才有后端数据的可用之处,查询的模块就相对比较多
1.单条记录查询(查询某个业务场景)
2.多条记录查询(查询列表,常见为商品列表,用户列表等)
3.按照某个字段排序查询(升序,降序)
4.分页查询
......
以上就是后端大概业务场景的分析
springboot代码是采用注解方式开发一般分为三部分:@Entity数据库类,JpaRepository接口类,@RestController业务实体类。

  • JpaRepository是用于整合业务查询模块。
    接下我们根据具体的场景来实现具体的springboot代码。

代码实践

springboot提供整套的封装方法,大量地减少了许多业务场景,接下来我们看看springboot为我们封装的常用方法,CrudRepository源码如下:

import java.util.Optional;
@NoRepositoryBean
public interface CrudRepository extends Repository {
    //保存对象
     S save(S var1);
     //根据迭代器来保存
     Iterable saveAll(Iterable var1);
    //根据id来查询值
    Optional findById(ID var1);
    //id是否存在
    boolean existsById(ID var1);
    //使用配置的TypeRepresentationStrategy来加载所有实体,可能会返回一个大的结果
    Iterable findAll();
    //根据迭代器查找
    Iterable findAllById(Iterable var1);
    // 使用配置的TypeRepresentationStrategy,根据策略,此数字可能是近似值
    long count();
    //根据迭代器查找id来删除给定的实体
    void deleteById(ID var1);
    //通过调用其entity.remove()方法删除给定实体
    void delete(T entity);
     //根据迭代器删除对象集合
    void deleteAll(Iterable var1);
    //删除此类型的所有实体,请小心使用
    void deleteAll();
}
  • 其中PagingAndSortingRepository 继承于CrudRepository
@NoRepositoryBean
public interface JpaRepository extends PagingAndSortingRepository, QueryByExampleExecutor {
    List findAll(); //查询全部

    List findAll(Sort var1);//排序查询

    List findAllById(Iterable var1);//根据id查询

     List saveAll(Iterable var1);
    //刷新对数据库的所有挂起更改。
    void flush();
    //保存实体并立即刷新更改。
     S saveAndFlush(S var1);
    //删除批处理中的给定实体,这意味着它将创建单个实体[`Query`]
    void deleteInBatch(Iterable var1);
    //删除批量调用中的所有实体。
    void deleteAllInBatch();
    //返回对具有给定标识符的实体的引用。
    T getOne(ID var1);
    
     List findAll(Example var1);

     List findAll(Example var1, Sort var2);
}

以上就是springboot给我们提供的封装常用方法的源码,下面我们来实战运用。

新增&更新

  • 在springboot中新增和更新都可以调用CrudRepository 中的save方法来保存数据。
    需求:注册用户
    场景:注册用户需要用户输入简单的手机号码,密码进行注册登录。并且生成用户特定uid字段。
数据类:
@Entity
public class User {
    //表id
    @Id
    @GeneratedValue
    private Integer id;
    //用户id
    private String uid;
    //用户昵称
    private String user_name;
    //用户电话
    private String user_phone
    //用户密码
    private String user_pwd;
    //get&set省略.....
}

JpaRepository接口类:

@Repository
public interface UserRepository  extends JpaRepository {}
业务类:
@RestController
@RequestMapping("/api")
@CrossOrigin
public class UserController {
    @Autowired
    private UserRepository userRepository;

    /**
     * 注册用户
     * @param user
     * @return
     */
    @PostMapping(value = "/register")
    public RespEntity addUser(User user) {
        if (user != null) {
            List users = userRepository.queryUser(user.getUserPhone());
            if (users == null) {
                //判断手机号是否正确
                if (!StringUtil.isExistLong(user.getUserPhone())) {
                    return new RespEntity(RespCode.WARN, "请输入手机号码");
                }
                //判断密码是否输入正确
                if (!StringUtil.isExist(user.getUserPwd(), 8)) {
                    return new RespEntity(RespCode.WARN, "请输入正确的密码");
                }
                //获取添加时间
                Long addtime = DateUtil.getTime();
                //将时间与手机号生成MD5编码
                String uid = MD5.md5(String.valueOf(addtime), user.getUserPhoto());
                if (uid!= null&&uid.length()>0) {
                    user.setUid(uid);
                    //保存数据
                    userRepository.save(user);
                    return new RespEntity(RespCode.SUCCESS, user);
                }else {
                    return new RespEntity(RespCode.WARN,"生成用户身份ID失败,请重试");
                }
            } else {
                return new RespEntity(RespCode.WARN, "用户已存在");
            }
        } else {
            return new RespEntity(RespCode.WARN);
        }
    }
}

以上就实现了注册用户,特别地简单。

  • RespEntity是返回封装。
  • StringUtil是判断数据字符是否为空工具类。
  • queryUser 方法是使用在JpaRepository中的 @Query条件查询实现的,后面会说明。
/**
     * 更新用户
     *
     * @param user
     * @return
     */
    @PostMapping(value = "/updatauser")
    public RespEntity updataUser(User user) {
        //查询是否有这个用户
        User oldUser = userRepository.findAll().get(user.getId());
        if (oldUser != null) {
           //如果用户存在就更新
            userRepository.save(user);
            return new RespEntity(RespCode.SUCCESS);
        } else {
            return new RespEntity(RespCode.WARN);
        }
    }

更新功能就这么简单,当然这还不够完善。

注意事项:
  • 建立每个表格都要增加时间字段,比如新增时间,更新时间,如果需要做接口访问统计的最好还要新增一个访问接口统计字段。
  • 访问数据的时候为了数据安全,都要对其进行身份验证。

删除

需求:删除(注销)用户
场景:根据用户手机号删除用户

  • 这里就需要用到JpaRepository功能,需要给他扩展接口方法,我现在需要一个根据用户手机号查询到该条数据的方法,如下:
 @Query(value = "select * from user as u where u.user_phone=?",nativeQuery = true)
    List queryUser(Long userPhone);

然后再在Controller中调用查询到该用户:

   @PostMapping(value = "/deluser")
    public RespEntity delUser(@RequestParam("userPhone") Long userPhone) {
        //查询是否有该手机用户
        List users=userRepository.queryUser(Long.valueOf(userPhone));
        if (users!=null&&users.size()>0){
            //获取该用户
            User user= users.get(0);
            if (user!=null){
                //调用删除
                userRepository.delete(user);
                return new RespEntity(RespCode.SUCCESS,"删除成功");
            }else{
                return new RespEntity(RespCode.WARN,"用户不存在");
            }

        }else {
            return new RespEntity(RespCode.WARN,"用户不存在,请重新输入");
        }

    }

查询

上面的增删改中,其实也提到几种查询方法:

  • 查询整个数据表findAll
repository.findAll();
  • 用户 @Query条件查询
@Query(value = "select * from user as u where u.user_phone=?",nativeQuery = true)
    List queryUser(Long userPhone);

然后比较常用的还有排序查询,eg:
需求:根据年龄大小排序查询用户

  • 首先我们需要在数据表类里新增一个年龄字段:
  @Column(name="user_sex")
    private Integer userSex;
  • @Column(name="user_sex") 代表把该字段作为排序字段,值为user_sex。
    /**
     * 查询文章列表#热度查询-阅读量
     */
    @GetMapping(value = "/like_usersex_list")
    public RespEntity findListSortSingleCondition() {
        Sort sort = new Sort(Sort.Direction.ASC, "user_sex");
        List userlist= userRepository.findAll(sort);
        if (userlist!= null && userlist.size() > 0) {
            return new RespEntity(RespCode.SUCCESS, userlist);
        } else {
            return new RespEntity(RespCode.WARN);
        }
    }
  • Sort 对象为排序条件对象,需要提交排序条件+排序按照升序还是降序。
    1.Sort.Direction.ASC 升序排列
    2.Sort.Direction.DESC 降序排列
  • 多条件查询
  /**
     * 多条件排序
     */
    public List findListSortMultiCondition() {
        List orders = new ArrayList();
        Sort.Order orderId = new Sort.Order(Sort.Direction.DESC, "id");
        Sort.Order orderAge = new Sort.Order(Sort.Direction.DESC, "user_sex");
        orders.add(orderId);s
        orders.add(orderAge);
        Sort sort = new Sort(orders);
        return userRepository.findAll(sort);
    }
  • 除此之外还有分页查询,springboot也提供了详细的分页查询api,就是利用Pageable ,如下:
@Query(value = "select u from  article u where u.name like  %?1% ")
    Page
findUserLikeByPage(String name, Pageable page);

总结

springboot还有很多乐趣,作为初学javaweb的人有很大便捷,至少对于我而言,不再是想以前那么提起后台开发就觉得是一件很高深莫测的东西,有些东西没有去接触尝试,就不要对其产生畏惧,那是自己杀死了自己。
三年前我有了小梦想就是成为全栈工程师,当初有人说,你能够把一项搞懂就行了,但是三年的今天,我已经跨出了那么一小步,虽然这一步很小,未来还很远,但是我还是想沿着这条路走下去,看看这条路未来的路是怎么样子的,万金油也好,我只是想活着自己想要活着的样子罢了。
既然想了,就去做吧,干嘛想那么多有的没的。

你可能感兴趣的:(全栈之路-Springboot初试)