1、记得启动Mysql服务!!
今天在做JavaWeb日志管理系统时发现,前端5173端口向后端8080端口发送服务时,返回的数据中data为空,以下是debug的学习记录。
首先在后端开启了调试模式,
结果偶然发现是自己mysql的服务没启(这下尴尬了)。
发现自己写的SysUser sysUser = userService.findByUsername(username)没有查询到用户。后来理清了业务逻辑,由于我写了一个合法的用户名,本就该查询不到,因此此处写的是正确的。
2、一个困扰了我许久时间的问题
问题如下:我们直到Dao接口和DaoImpl封装了一些和数据库进行交互的方法,但在Controller层有些业务的逻辑与Dao封装的方法完全一致,我们为什么要再在service封装而不直接调用Dao层的方法呢?
以下是我在ChatGpt找到的回答:
1、service层与Dao层解耦,也就是业务逻辑代码与数据访问代码解耦,这样在service层修改代码,不会需要改变我在Dao层写好的代码。
2、我不能只考虑service的业务正好与Dao层代码匹配的情况,大多数情况service中封装的一个方法是需要调用多个Dao层的方法的。
3、剩下的就是blablabla了,但我觉得,上面两点已经完全够分量说服我了。
3、后端代码掰扯
我们新建了一个SysUser对象来接受返回的信息(成功返回对象,不成功则返回null)。
String username = req.getParameter("username"); SysUser sysUser = userService.findByUsername(username); Result result = null; if(null == sysUser){ //此处的逻辑是,如果数据库没有查询到,那么该用户名是合法的。 result = Result.ok(null); } else{ result=Result.build(null, ResultCodeEnum.USERNAME_USED); } //用webUtil将对象转化为JSON串 WebUtil.writeJson(resp,result);
上述代码我仍然需要掌握的,首当其冲的就是这个Result对象了,之前学习时我隐约了解到这是前后端进行数据统一的,但我认为还需要掰扯,我们来看看代码。
public class Result<T>{ private Integer code; private String message; private T data; //下面是封装的一些方法,我们等下在看 }
首先我们为什么需要封装一个Result类?他是为了接口的设计更加健壮和易于维护(可以理解)。我们当然希望调试接口的时候,无论测试哪个接口,都能收到一个结构一致的响应(这个说服性就很强啦)。
Result类里我们封装了三个成员变量
1、状态码code
2、消息message
3、数据data
private T data;
为什么数据data要这样定义呢?首先这个T不是空穴来风,他是你定义Result<T>的时候就出现了的。他表示任意类型,具体什么类型是实际调用的时传入的类型
protected static <T> Result<T> build(T data) { Result<T> result = new Result<T>(); if (data != null) result.setData(data); return result; } public static <T> Result<T> build(T body, Integer code, String message) { Result<T> result = build(body); result.setCode(code); result.setMessage(message); return result; } public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) { Result<T> result = build(body); result.setCode(resultCodeEnum.getCode()); result.setMessage(resultCodeEnum.getMessage()); return result; }
接下来是我们为什么要创建Result的build方法?
首先明确,我们定义的build方法都是静态方法,他可以直接通过类名调用并返回一个Result对象,但他不需要创建一个Result对象。
我们为什么使用build静态方法,而不使用构建方法呢?(这是我难以理解的地方)
1、自定义初始化逻辑:
2、工厂方法模式:
build
方法通常被视为一种工厂方法模式(Factory Method),这种模式用于为客户端提供创建对象的统一接口,而不是直接使用构造方法。这种模式可以使代码更加灵活,尤其是在需要根据条件返回不同子类实例的情况下。
4、泛型
在刚才发现自己对泛型的理解不够,因此写一个记录来记录自己对泛型的学习。
在Java5之前,是通过Object对象来解决这类复用性不高的问题的。这里需要注意下
ObjectHolder h2 = new ObjectHolder(new AutoMobile());
这种构造方式是合法的,ObjectHolder的构造函数中传入的实际上是AutoMobile构造器构造的对象的引用。
<T> Result<T> 要看做两部分,第一个<T>表示这是一个泛型方法,你在后面的参数中可能也会传入泛型参数,而后面的Result<T>是泛型类。
5、WebUtil
在WebUtil中,我定义了Json串转换的方法,现在来详细解读一下。在WebUtil中我们要定义了json与object的转化方法,需要引用jackson库,利用其中的objectMapper来实现。
//创建静态的objectMapper private static ObjectMapper objectMapper; //静态代码块,便于添加额外的初始化 static{ objectMapper = new ObjectMapper(); objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); } //读JSON方法 public static<T> T readJson(HttpServletRequest request, Class<T> clazz){} //写JSON方法 public static void writeJson(HttpServletResponse response, Result result){}
6、BaseDao
BaseDao类定义了一些通用的数据库操作方法。使用了JDBC进行数据库交互,结合反射机制来将查询结果映射到Java对象中。
这里涉及到JDBC和反射的内容,需要我进一步学习。