MVC架构模式-各层的写法要求

MVC架构模式-各层的写法要求

M层中大概包括:pojo层、Dao层、Service层

C层中包括:Controller层

注意事项:

  • 要在接口上写明方法的文档
  • 无论哪个层在调用其他层对象时,最好将其实例化对象为类中属性,这样做可以不用在每个方法中都实例化对象
  • 写代码的逻辑可以选择为:Controller -> service -> Dao (由前向后),先写调用 再写 方法内容

pojo层

  • 实体类中的类名与表格名称应该对应
  • 实体类的属性名与表格的列明应该对应
  • 遇到下划线应以驼峰命名进行转换
  • 每个属性都应该是私有的
  • 每个属性都应该具备get/set方法
  • 必须具备无参构造器
  • 应该实现序列化接口(缓存 分布式项目数据传递 可能会将对象序列化)
  • 应该重写hashcode和equals方法
  • toString是否重写都可以

以上我们只需要注意加粗部分,其余部分使用Lombok注解即可在编译时自动生成😓

Lombok的使用方法
  • 检查idea是否已经安装了Lombok插件
  • 检查是否勾选了enable annotation precessing

在汉化后的idea中,此设置在 构建、执行、部署 -> 编译器 -> 注解处理器 -> 启用注解处理

  • 导入Lombok的依赖添加jar包
  • 在实体类中添加Lombok注解
@AllArgsConstructor //添加全参构造
@NoArgsConstructor //添加无参构造
@Data //添加get/set/hashcode/equals

DAO层

参考JDBC模块知识点进行编写

  • dao
    • impl目录:用于存放接口的实现类
    • BaseDAO类
    • xxxDao接口:用于定义Dao类功能的接口

Service层

  • service
    • impl目录:用于存放接口的实现类
    • xxxService接口:用于定义service功能的接口(调用Dao层实现功能)

Controller层

为了区分功能的调用,我们将功能接在URI后的新增一层

例如:本Servlet的访问路径为/xxx,可以在URI加一级路径

增加的请求 :/xxx/add

删除的请求 :/xxx/remove

修改的请求 :/xxx/update

查询的请求 :/xxx/find


在service方法中,通过分割URI的方式,提取出要请求的功能,分别调用

注:WebServlet注解要写成("/xxx/*")

String[] split = req.getRequestURI().split("/");//URI:/schedule/xxx
switch (split[split.length - 1]) {
    case "add": add(req, resp); break;
    case "update": update(req, resp); break;
    case "remove": remove(req, resp); break;
    case "find": find(req, resp); break;
    default: break;
}

可以看出,URI中的功能名和我们调用的方法名一致

所以,以上代码我们可以通过反射,使用分割URI的方式提取出功能名,再使用功能名调用方法!!! 😊

String[] split = req.getRequestURI().split("/");//URI:/schedule/xxx

Class<? extends SysScheduleController> clazz = getClass();
try {
    Method declaredMethod = clazz.getDeclaredMethod(split[split.length - 1], HttpServletRequest.class, HttpServletResponse.class);//通过反射,使用功能名获得即将要执行的方法
    declaredMethod.setAccessible(true);//设置方法穿透
    declaredMethod.invoke(this,req,resp);//调用方法啊,传参
} catch (Exception e) {
    e.printStackTrace();
}

这种编程思想使得代码的泛用性更高,只需要增加方法即可


再将增删改查的方法封装

protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("add");
}
protected void remove(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("remove");
}
protected void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("update");
}
protected void find(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("find");
}

BaseController

基于以上思想,我们将公共代码提取出一个BaseController的父类,提高代码的复用性

与BaseDAO类似,我们可以将实现类继承此类,并且不再需要继承HttpServlet类

实现类中可以不用重写service方法,直接写功能方法即可

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.lang.reflect.Method;

/**
 * 注:WebServlet注解要写成("/xxx/*")
 * 此类封装:通过URI分割获取功能名反射到Controller层执行方法的功能实现
 * 其他Controller类直接继承此类即可(不需要再额外继承HttpServlet类,因为本类已经继承)
 */
public class BaseController extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String[] split = req.getRequestURI().split("/");
        
        Class<? extends BaseController> clazz = getClass();
        try {
            Method declaredMethod = clazz.getDeclaredMethod(split[split.length - 1], HttpServletRequest.class, HttpServletResponse.class);
            declaredMethod.setAccessible(true);
            declaredMethod.invoke(this,req,resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

MD5加密工具类

MD5 常被用于对密码等敏感信息进行单向加密,以便存储在数据库中,而不需要存储原始明文密码

他是一个常量类(静态方法),通常用于在service层,对明文密码进行处理再发到数据库储存

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public final class MD5Util {
    public static String encrypt(String strSrc) {
        try {
            char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
                    '9', 'a', 'b', 'c', 'd', 'e', 'f' };
            byte[] bytes = strSrc.getBytes();
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(bytes);
            bytes = md.digest();
            int j = bytes.length;
            char[] chars = new char[j * 2];
            int k = 0;
            for (int i = 0; i < bytes.length; i++) {
                byte b = bytes[i];
                chars[k++] = hexChars[b >>> 4 & 0xf];
                chars[k++] = hexChars[b & 0xf];
            }
            return new String(chars);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException("MD5加密出错!!!")
        }
    }
}