做Java开发,你需要了解这些(下)

简介: 做Java开发,你需要了解这些

五、使用BeanUtils进行属性拷贝:


上面说到把从数据库查到的productInfo的属性的值赋给productInfoVo对应的属性,这里说一下赋值的问题:


ProductInfo类如下:

@Entity
@Data
public class ProductInfo {
    @Id
    private String productId;
    private String productName;
    private BigDecimal productPrice;
    private Integer productStock;//库存
    private String productDescription;//描述
    private String productIcon;//小图
    private Integer productStatus;//商品状态(0正常,1下架)
    private Integer categoryType;//类目编号
}


ProductInfoVo类上面已给出,对比可以发现,ProductInfoVo与ProductInfo相比,就是少几个属性。我们现在从数据库查出来的是productInfo,而前端需要的是productInfoVo,所以需要将productInfo里的值设置到productInfoVo里去。常规做法是先从productInfo中get再set到productInfoVo中去:

ProductInfo productInfo = productService.findOne(productId);
ProductInfoVo productInfoVo = new ProductInfoVo();
productInfoVo.setProductName(productInfo.getProductName());
productInfoVo.setProductPrice(productInfo.getProductPrice());
......


如果属性少问题也不大,如果属性很多,那么就要写一大堆这样的代码。可以使用spring提供的一个属性拷贝工具,不管多少个属性,只需一行代码:

BeanUtils.copyProperties(productInfo, productInfoVo);


这就表示把productInfo的属性拷贝到productInfoVo对象中去。


注意:使用这个工具有两点要注意,第一个就是这两个对象的属性名要一致;第二就是null值也会拷贝进去,所以如果productInfo中有个属性值为null,进行拷贝后productInfoVo对应的属性值也会是null,就算拷贝之前设置了值也会覆盖掉,所以要先拷贝再赋值。


六、dto的使用:


dto全称是data transfer object,中文意思为数据传输对象。那么dto有什么作用?什么时候该用dto?如何使用呢?看下面的例子:


假如我数据库有两张表,一张学生表student,一张班级表class。它们对应的实体类如下:

@Data
public class Student {
    @Id
    private String studentId;
    private String classId;
    private String name;
}

@Data
public class Class {
    @Id
    private String classId;
    private String  className;
}


假如我现在要查一个班级的信息,班级应该是包含了多个学生的,因为一个班级有多个学生,那么通常class实体类应该这样设计:

@Data
public class Class {
    @Id
    private String classId;
    private String  className;
    private List<Student> studentList;
}


那么问题来了,这样实体类和表就对应不上了,因为在class表中没有与studentList这个属性对应的字段。虽然可以在studentList上加上@Transient注解,这样jpa在与数据表对应时就会忽略这个属性。但是这样不好,感觉就是污染了这个与数据表对应的实体类,我们还是要让实体类与数据表 一 一对应,所以class类不能增加这个字段。那么我们就新建一个实体类,叫ClassDto:

@Data
public class ClassDto {
    private String classId;
    private String  className;
    private List<Student> studentList;
}


这就是dto的作用,最常用的就是当某两个实体类存在关系时,而数据表对应的实体类为了跟数据表一致,没有体现这种关系,那么就可以使用dto。dto不对应数据表,所@Id注解也不需要了。


七、异常处理:


平时我们用异常可能直接throw一个exception就完事了,但是这样不好,因为这样抛出去自己也看不懂是什么异常,所以可以像下面这样处理:


自定义一个异常类继承RuntimeException:

public class GlobalException extends RuntimeException{
    private Integer code;
    public GlobalException(ExceptionEnum exceptionEnum ){
        super(resultEnum.getMessage());
        this.code = resultEnum.getCode();
    }
    public GlobalException(Integer code,String message){
        super(message);
        this.code = code;
    }
}


用到的枚举类:

@Getter
public enum ExceptionEnum {
    PRODUCT_NOT_EXIST(10,"商品不存在"),
    PRODUCT_STOCK_ERROR(11,"库存不足"),
    ;
    private Integer code;
    private String message;
    ExceptionEnum (Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}


自定义一个异常类,搭配枚举一起使用。那么在抛异常的时候就可以这样写:

throw new GlobalException(ExceptionEnum.PRODUCT_NOT_EXIST);


这样前端就可以看到“商品不存在”这样的提示,而不是一串看不懂的异常。枚举类种我只是列举了两个例子,有异常就可以往枚举种添加,然后像上面那样用就行了。


八、生成随机数:


有时候数据表的Id没有设置自增,需要我们自己设置Id。Id要求是必须唯一,提供如下工具类:

public class KeyUtil {
    /**
     * 生成唯一主键
     * 格式:当前时间+随机数
     */
    public static synchronized String genUniqueKey(){
        Random random = new Random();
        //Integer a =random.nextInt(90) + 10;//生成两位随机数
        //生成六位随机数
        Integer number =random.nextInt(900000) + 100000;
        return  System.currentTimeMillis() + String.valueOf(number);
    }
}


九、表单验证:


前端给后台传参数的时候,我们要在controller中获取前端传入的参数,一般有以下几种做法:


  • HttpServletRequest:


用这个一般要编写一个工具类,用来获取指定类型的参数:

public class HttpServletRequestUtil {
    public static int getInt(HttpServletRequest request, String name) {
        try {
            return Integer.decode(request.getParameter(name));
        } catch (Exception e) {
            return -1;
        }
    }
    public static long getLong(HttpServletRequest request, String name) {
        try {
            return Long.valueOf(request.getParameter(name));
        } catch (Exception e) {
            return -1;
        }
    }
    public static Double getDouble(HttpServletRequest request, String name) {
        try {
            return Double.valueOf(request.getParameter(name));
        } catch (Exception e) {
            return -1d;
        }
    }
    public static Boolean getBoolean(HttpServletRequest request, String name) {
        try {
            return Boolean.valueOf(request.getParameter(name));
        } catch (Exception e) {
            return false;
        }
    }
    public static String getString(HttpServletRequest request, String name) {
        try {
            String result = request.getParameter(name);
            if (result != null) {
                result = result.trim();
            }
            if ("".equals(result))
                result = null;
            return result;
        } catch (Exception e) {
            return null;
        }
    }
}


然后在controller中这样用:

@RequestMapping(value = "/getproductlistbyshop")
public ResultVo list(HttpServletRequest request) {
        // 获取前台传过来的页码
        int pageIndex = HttpServletRequestUtil.getInt(request, "pageIndex");
        // 获取前台传过来的每页显示的数量
        int pageSize = HttpServletRequestUtil.getInt(request, "pageSize");
                ......
}


但是这样获取参数,如果要校验的话需要自己写if语句来判断,比如:

if (pageIndex == null || pageSize == null){
    log.error(...);
    throw new GlobalException(...);
}


看第二种获取前端参数的方法:


  • @RequestParam:

@GetMapping("/list")
 public ResultVo list(@RequestParam(value = "page",defaultValue = "0") Integer page,
                      @RequestParam(value = "size",defaultValue = "10") Integer size){
       ......    
    }


用这个还可以用defaultValue指定默认值,当前端没传时默认就为defaultValue指定的值。这种方法呢其实就是第一种方法的注解形式,如果要对获取的参数判断,还是要自己写if语句。


接下来看第三种方法:


  • 表单对象:
    如果前端传过来的参数很多,用上面两种方法写未免有些麻烦,而且还要自己一个个的判断传过来的参数是否为空,为空的话又要给前端什么提示。我们可以把前端的参数封装成一个对象,然后在controller中直接获取该对象即可,而且对于参数的验证都可以在封装的这个对象中完成,这就是springmvc提供的表单验证。看例子:

@Data
public class OrderForm {
    @NotEmpty(message = "姓名必填")
    private String name;
    @NotEmpty(message = "手机号必填")
    private String phone;
    @NotEmpty(message = "地址必填")
    private String address;
    @NotEmpty(message = "openid必填")
    private String openid;
    @NotEmpty(message = "购物车不能为空")
    private String items;
}


比如从前端获取的参数有这么多,那么就可以封装成这样一个OrderForm表单对象。加上@NotEmpty注解就表示这个参数不能为空,里面的message就是当该参数为空时给前端的提示。接下来看如何在controller中使用该对象:

@PostMapping("/create")
 public ResultVo create(@Valid OrderForm orderForm, BindingResult bindingResult){
      //判断表单校验后有没有错误
      if (bindingResult.hasErrors()) {
          log.error("【创建订单】参数不正确,orderForm={}",orderForm);
          throw new GlobalException(ExceptionEnum.PARAM_ERROR.getCode(),
                    bindingResult.getFieldError().getDefaultMessage());
      }
      ......
}


@Valid注解就可以使用该对象,bindingResult就是验证的结果,如果验证参数不正确,通过bindingResult.getFieldError().getDefaultMessage()就可以获取到刚才@NotEmpty注解里面message的内容,配合全局异常使用,就可以把这个message返回给前端。


总结:


上面的介绍的lombok、创建时间和更新时间的处理、BeanUtils的使用都可以减少代码量,而dto、vo、全局异常处理、表单验证等可以使代码结构更加清晰,使程序更加健壮。希望大家喜欢!




相关文章
|
1月前
|
Java
Java开发实现图片URL地址检验,如何编码?
【10月更文挑战第14天】Java开发实现图片URL地址检验,如何编码?
68 4
|
8天前
|
Java API Maven
如何使用Java开发抖音API接口?
在数字化时代,社交媒体平台如抖音成为生活的重要部分。本文详细介绍了如何用Java开发抖音API接口,从创建开发者账号、申请API权限、准备开发环境,到编写代码、测试运行及注意事项,全面覆盖了整个开发流程。
52 10
|
1月前
|
监控 Java 测试技术
Java开发现在比较缺少什么工具?
【10月更文挑战第15天】Java开发现在比较缺少什么工具?
36 1
|
1月前
|
Java
Java开发实现图片地址检验,如果无法找到资源则使用默认图片,如何编码?
【10月更文挑战第14天】Java开发实现图片地址检验,如果无法找到资源则使用默认图片,如何编码?
59 2
|
14天前
|
SQL 安全 Java
安全问题已经成为软件开发中不可忽视的重要议题。对于使用Java语言开发的应用程序来说,安全性更是至关重要
在当今网络环境下,Java应用的安全性至关重要。本文深入探讨了Java安全编程的最佳实践,包括代码审查、输入验证、输出编码、访问控制和加密技术等,帮助开发者构建安全可靠的应用。通过掌握相关技术和工具,开发者可以有效防范安全威胁,确保应用的安全性。
32 4
|
16天前
|
缓存 监控 Java
如何运用JAVA开发API接口?
本文详细介绍了如何使用Java开发API接口,涵盖创建、实现、测试和部署接口的关键步骤。同时,讨论了接口的安全性设计和设计原则,帮助开发者构建高效、安全、易于维护的API接口。
43 4
|
26天前
|
开发框架 JavaScript 前端开发
HarmonyOS UI开发:掌握ArkUI(包括Java UI和JS UI)进行界面开发
【10月更文挑战第22天】随着科技发展,操作系统呈现多元化趋势。华为推出的HarmonyOS以其全场景、多设备特性备受关注。本文介绍HarmonyOS的UI开发框架ArkUI,探讨Java UI和JS UI两种开发方式。Java UI适合复杂界面开发,性能较高;JS UI适合快速开发简单界面,跨平台性好。掌握ArkUI可高效打造符合用户需求的界面。
84 8
|
21天前
|
SQL Java 程序员
倍增 Java 程序员的开发效率
应用计算困境:Java 作为主流开发语言,在数据处理方面存在复杂度高的问题,而 SQL 虽然简洁但受限于数据库架构。SPL(Structured Process Language)是一种纯 Java 开发的数据处理语言,结合了 Java 的架构灵活性和 SQL 的简洁性。SPL 提供简洁的语法、完善的计算能力、高效的 IDE、大数据支持、与 Java 应用无缝集成以及开放性和热切换特性,能够大幅提升开发效率和性能。
|
22天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
41 2
|
22天前
|
监控 Java 数据库连接
在Java开发中,数据库连接管理是关键问题之一
在Java开发中,数据库连接管理是关键问题之一。本文介绍了连接池技术如何通过预创建和管理数据库连接,提高数据库操作的性能和稳定性,减少资源消耗,并简化连接管理。通过示例代码展示了HikariCP连接池的实际应用。
19 1