Java新手村《瑞吉外卖》笔记

瑞吉外卖笔记

1. Controller返回自定义对象自动转JSON格式

在开发项目的时候,返回给前端的数据,需要将数据封装到集合或者自定义对象中。但是前端需要的是JSON格式的字符串,如果我们将集合或者自定义对象直接返回给前端,前端无法接收到数据。

因此,我们需要将集合或者自定义对象转成JSON格式的字符串,每次使用代码进行转换有点繁琐,我们需要让Spring MVC自动帮我们将集合或者自定义对象转成JSON格式的字符串。
如果是Spring Boot项目,直接返回集合或者自定义对象即可,框架会自动将集合或者字符串自动转成JSON格式的字符串。

如果是SSM项目,使用@RestController或者@ResponseBody注解后,我们还需要添加配置,Spring MVC才能自动将集合或者自定义对象转成JSON格式。

原文链接:https://blog.csdn.net/weixin_44843569/article/details/118864444

2. java实体类中实现序列化接口有什么作用

3. 关于Springboot的@Service注入的方式

4. @RequestBody

@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);而最常用的使用请求体传参的无疑是POST请求了,所以使用@RequestBody接收数据时,一般都用POST方式进行提交。

@PostMapping
   public R<String> save(HttpServletRequest request, @RequestBody Employee employee) {
       log.info("新增员工信息:{}", employee.toString());
       // 设置默认密码为123456 并进行MD5加密
       employee.setPassword(DigestUtils.md5DigestAsHex(CommonsConst.INIT_PASSWORD.getBytes()));
       //使用MybatisPlus的元对象处理器 自动填充公共字段 代理下面的代码:

       // 设置创建时间
       // employee.setCreateTime(LocalDateTime.now());
       // 设置更新时间
       // employee.setUpdateTime(LocalDateTime.now());
       // 用户ID设置(session中取得)
       // Long empId = (Long) request.getSession().getAttribute("employee");
       // employee.setCreateUser(empId);
       // employee.setUpdateUser(empId);
       // 调用存储方法
       employeeService.save(employee);
       return R.success("添加成功");
   }

5. Java中的session存储

  • 前端存储之sessionStorage和localStorage

  • sessionid是一个会话的key,浏览器第一次访问服务器会在服务器端生成一个session,有一个sessionid和它对应。tomcat生成的sessionid叫做jsessionid。

  • session在访问tomcat服务器HttpServletRequest的getSession(true)的时候创建,tomcat的ManagerBase类提供创建sessionid的方法:随机数+时间+jvmid。

  • 存储在服务器的内存中,tomcat的StandardManager类将session存储在内存中,也可以持久化到file,数据库,memcache,redis等。客户端只保存sessionid到cookie中,而不会保存session,session销毁只能通过invalidate或超时,关掉浏览器并不会关闭session。

  • 那么Session在何时创建呢?当然还是在服务器端程序运行的过程中创建的,不同语言实现的应用程序有不同创建Session的方法,而在Java中是通过调用HttpServletRequest的getSession方法(使用true作为参数)创建的。在创建了Session的同时,服务器会为该Session生成唯一的Session id,而这个Session id在随后的请求中会被用来重新获得已经创建的Session;在Session被创建之后,就可以调用Session相关的方法往Session中增加内容了,而这些内容只会保存在服务器中,发到客户端的只有Session id;当客户端再次发送请求的时候,会将这个Session id带上,服务器接受到请求之后就会依据Session id找到相应的Session,从而再次使用之。

  • 创建:sessionid第一次产生是在直到某server端程序调用HttpServletRequest.getSession(true)这样的语句时才被创建。

  • 删除:超时;程序调用HttpSession.invalidate();程序关闭。

  • session存放在哪里:服务器端的内存中。不过session可以通过特殊的方式做持久化管理(memcache,redis)。

  • session的id是从哪里来的,sessionID是如何使用的:当客户端第一次请求session对象时候,服务器会为客户端创建一个session,并将通过特殊算法算出一个session的ID,用来标识该session对象。

  • session会因为浏览器的关闭而删除吗?不会,session只会通过上面提到的方式去关闭。转载:session存到哪里

6. 公共字段填充

MybatisPlus 公共字段自动填充,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免了重复代码;

实现步骤:

  1. 在实体类的属性上(需要自动填充的字段)加入@TableField注解,指定自动填充的策略;
  2. 按照框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,此类需要实现 MP提供的 MetaObjectHandler接口。

7. 将用户ID存入HttpSession改存入ThreadLocal,客户端同次请求下的操作可动态获取登录用户ID

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • ThreadLocal并不是一个Thread,而是Thread的一个局部变量。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每个线程都可以独立地改变自己的副本,而不影响其他线程所对应的副本。ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。
    1. ThreadLocal ---->public void set(T value) 设置当前线程的线程局部变量的值;
    2. MetaObjectHandler ---->updataFill( ) 方法内就可以调用线程的get方法获取线程局部变量值。
  • 基于ThreadLocal封装工具类BaseContext,用户保存和获取当前登录用户id。
  • 工具类:里面的方法都定义为static 静态方法,通过工具类直接调用,注意这里就体现了单例模式的用法(饿汉单例):类第一次类加载就为了自己创建了一个实例对象,后续调用工具类的方法,都是同一个实例对象。
public class BaseContext {
    private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
    public static void setCurrentId(Long id){
        threadLocal.set(id);
    }
    public static Long getCurrentId(){
        return threadLocal.get();
    }
}
  • 具体流程:
  1. 在过滤器代码里就使用工具类存储用户id:
		//4-1 判断登陆状态,若已经登陆直接放行
        if (request.getSession().getAttribute("employee") != null) {
            log.info("用户已登录,id为:{}", request.getSession().getAttribute("employee"));

            //验证当前线程id
            Long empId = (Long) request.getSession().getAttribute("employee");
            BaseContext.setCurrentId(empId);

            long id = Thread.currentThread().getId();
            log.info("线程ID为:{}", id);

            filterChain.doFilter(request, response);
            return;
        }
        //若未登陆则返回未登陆结果
        response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
        return;
  1. 然后在元对象处理器(通过实现MybatisPlus的MeataObjectHandler接口,自动填充公共字段)里通过BaseContext获取线程局部变量值,从而获取”createUser“和”updateUser“的值:
@Component
@Slf4j
public class MyMetaObjecthandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("公共字段自动填充[insert]...");
        log.info(metaObject.toString());
        metaObject.setValue("createTime", LocalDateTime.now());
        metaObject.setValue("updateTime",LocalDateTime.now());
        metaObject.setValue("createUser", BaseContext.getCurrentId());
        metaObject.setValue("updateUser", BaseContext.getCurrentId());
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("公共字段自动填充[update]...");
        log.info(metaObject.toString());
        /*
         验证当前线程id
         long id = Thread.currentThread().getId();
         log.info("线程id为:{}",id);
        */
        metaObject.setValue("updateTime",LocalDateTime.now());
        metaObject.setValue("updateUser",BaseContext.getCurrentId());
    }
}

8. DTO

表现层与应用层之间是通过数据传输对象(DTO)进行交互的,数据传输对象是没有行为的POCO对象,它 的目的只是为了对领域对象进行数据封装,实现层与层之间的数据传递。为何不能直接将领域对象用于 数据传递?因为领域对象更注重领域,而DTO更注重数据。不仅如此,由于“富领域模型”的特点,这样 做会直接将领域对象的行为暴露给表现层。

需要了解的是,数据传输对象DTO本身并不是业务对象。数据传输对象是根据UI的需求进行设计的,而不 是根据领域对象进行设计的。比如,Customer领域对象可能会包含一些诸如FirstName, LastName, Email, Address等信息。但如果UI上不打算显示Address的信息,那么CustomerDTO中也无需包含这个 Address的数据

简单来说Model面向业务,我们是通过业务来定义Model的。而DTO是面向界面UI,是通过UI的需求来定义的。通过DTO我们实现了表现层与Model之间的解耦,表现层不引用Model,如果开发过程中我们的模型改变了,而界面没变,我们就只需要改Model而不需要去改表现层中的东西。
转载:我们为什么需要DTO(数据传输对象)

9. Git

在这里插入图片描述

10. Linux

复制文件到指定文件:

cp ./指定文件 指定文件目录

在这里插入图片描述

Vim 文本编辑器:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
查看进程:

在这里插入图片描述停止Tomcat服务的方式:
在这里插入图片描述

防火墙操作:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

11. Redis

在这里插入图片描述
在这里插入图片描述

  • vim redis.conf 设置后台打开服务 ( daemonize yes)
    后续打开redis服务: src/redis-server ./redis.conf
  • vim redis.conf 设置需要密码 (requeirepass 123456)
    后续登录: src/redis-cli -h localhost -p 6379 -a 123456
    在这里插入图片描述
  • vim redis.conf 取消只能本地连接redis服务,然后就能远地连接redis服务。
    (将bind 127.0.0.1 注释掉) 同时还要把防火墙打开(
    开放指定端口:firewall-cmd --zone=public --add-port=6379/tcp --permanent
    立即生效:firewall-cmd --reload
    查看开放的端口: firewall–cmd --zone=public --list-ports
    最后还要重启服务:ps -ef | grep redis kill -9 [进程号] src/redis.server ./redis.conf
    )。
    在这里插入图片描述
    Redis中文教程
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

12. Redis缓存短信验证码

在这里插入图片描述

13. Redis缓存菜品数据

在这里插入图片描述
在这里插入图片描述

14. Spring Cache

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

15. MySQL 主从复制

在这里插入图片描述

16. Sharding-JDBC实现读写分离

在这里插入图片描述

17. Nigix

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

18. Swagger

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

19. 项目部署

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值