首页 > 其他分享 >spring-boot(廖师兄微信下单系统)学习笔记

spring-boot(廖师兄微信下单系统)学习笔记

时间:2023-08-03 15:45:57浏览次数:35  
标签:category product 缓存 spring boot key 微信 categoryType public

1、lombok工具

1.1、依赖 groupId:org.projectlombok;artifactId:lombok 1.2、idea 要安装lombok plugin 1.3、作用: 对model类加一个@Data注解就可以省写set and get方法 对类加@Slf4j注解可以直接通过log调用日志方法 对类加@Getter注解就可以省去写get方法

2、不要在for中有查询数据库行为,会影响性能

3、数据的更新,先查询出来,再通过set方法更新要更新的字段再将整个对象更新

4、@JsonProperty("name")注解VO层bean属性,可以重新指定返回前端的字段名

5、java8,lambda的作用:从对象List中获取某个字段并将其放入集合中

eg:List ageList = personList.stream().map(e->e.getAge()).collect(Collectors.toList()); eg:List contactList = personList.stream().map(e-> new Contact(e.getPhone(),e.getName()) ).collect(Collectors.toList());

6、开发中常用到将model中的大部分属性set到vo对象中,可以使用BeanUtils.copyProperties(model,vo);

但要注意,如果model属性的值是null,也会copy过去。

7、判断是否为空:

7.1 集合:CollectionUtils.isEmpty({集合对象}) 7.2 字符串:StringUtils.isEmpty({String})

8、controller下方法加参数BindingResult bindingResult, 可以通过bindingResult.hasErrors()判断参数校验是否有误。

9、使用Gson将json字符串转化为List对象:gson.fromJson({String},new TypeToken<{List}>(){}.getType());

10.JsonSerializer的作用:可以实现对对象属性值进行统一重写

用法:10.1 写一个class 继承 JsonSerializer<{对象属性类型}> 10.2 重写serialize方法,在方法中可以对属性值进行处理 10.3 在用到此重写的对象属性上使用注解:@JsonSerialize(using={类.class})

11、Page<{vo}>对象,vo->另外一个vo1的方法:

11.1 将List转成List:可以使用java8,lambda进行转换 11.2 Page <- new PageImpl({List},{Pageable},{List})

12、配置文件中值的获取:

12.1 @ConfigurationProperties(prefix=前缀):将配置文件中的值映射到一个bean的属性(可以为Map<String,String>())中 12.3 类中引用 @Autowired private Environment env; 通过 env.getProperty(“ms.db.username”)可以获取

13、微信微信开发:

13.1 第三方工具SDK:https://github.com/wechat-group/weixin-java-tools 13.2 第三方支付SDK:https://github.com/Pay-Group/best-pay-sdk 13.2 授权时如果提示redirect_uri参数错误,说明配置网页授权获取用户基本信息填写的域名不对

14、www.ibootstrap.cn 可以快速生成前端代码

15、枚举的更高级使用:视频的卖家-订单-controller(下)15:00

16、JSON接口注解:

16.1 @JsonIgnore:如果某个对象的属性不想出现在生成的json中,可以在属性上加上此注解 16.2 @JsonInclude(Include.NON_NULL)如果某个对象的属性值为null时,不想出现在生成的json中,可以在类上加上此注解

17、controller与service层,逻辑分工:如果与用户权限判断相关的逻辑,那就在controller进行,其他逻辑应以操作为单位,写在service层,方便重用

18、freeMarker

18.1 List语法:<#list 1..{num} as index></#list> 可以遍历出1到{num}之间的整数,常用于翻页 18.2 ${}内的变量可以进行运算 18.3 如果修改了模板内容,可以使用build project进行刷新,不需要重启 18.4 ${(值)!””}:意思是如果值拿不到,就显示””,值要加括号 18.5 html标签内可以嵌套freeMarker标签

19、@Bean注解的方法,在其它类中的引用:@Autowired private 方法返回类型 方法名

20、redis:使用时注意一定要设置过期时间

20.1 连接管理工具:redis desktop manager 20.2 依赖:spring-boot-starter-data-redis 20.3 参数配置:spring.redis.host=127.0.0.1;spring.port=6379(直接配置就行了,spring会自动去读取) 20.4 @Autowired private StringRedisTemplate redisTemplate(当然还可以使用其它类型模板) 20.5 redisTemplate.opsForValue().set(key,value,time,TimeUnit.SECOND); 20.6 redisTemplate.opsForValue().getOperations().delete(key);

21、cookie:

21.1 设置:Cookie cookie = new Cookie(key,value); cookie.setPath("/"); cookie.setMaxAge(7200); response.addCookie(cookie); 21.2 获取:Cookie[] cookies = request.getCookies(); Cookie cookie1 = null; for(Cookie cookie:cookies){     if(cookie.getName().equals({name})){         cookie1 = cookie;     } } 21.3 清除:只要将过期时间设置为0  

22、ModelAndView:

22.1 重定向时要使用完整的http地址 new ModelAndView("redirect:http://xxxx.xxx.cxx")

23、 aop 

23.1 类加@Aspect注解 23.2 切入点:@Pointcut("execution(public * com.imooc.controller.Seller*.*(..)) && !execution(public * com.imooc.controller.SellerUserController.*(..))")       public void verify(){} 23.3 进行拦截 @Before("verify()") //指定切入点 public void doVerify(){     //1、获取requeste     ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();     HttpServletRequest request = attributes.getRequest();     //2、查询cookie,如果校验不通过就抛出异常(使用统一异常拦截处理)     //3、查询redis,如果校验不通过就抛出异常(使用统一异常拦截处理) }

24、拼接

24.1 字符串的拼接可以使用concat({String})方法

25、消息类的异常,只打印日志,不要抛出(不然后影响到正常的逻辑)

26、webSocket服务端:

26.1 引入依赖:spring-boot-starter-websocket 26.2 ServerEndpointExporter注入ioc容器: @Component public class WebSocketConfig{     @Bean     public ServerEndpointExporter serverEndpointExporter(){         return new ServerEndpointExporter();     } } 26.3 WebSocket @Component @ServerEndpoint("/WebSocket") public class WebSocket{     private Session session;     private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<>();       @OnOpen     public void onOpen(Session session){         this.session = session;         webSocketSet.add(this);     }       @OnClose     public void onClose(){                 webSocketSet.remove(this);     }       @OnMessage     public void onMessage(String message){                 System.out.println("收到客户端发来的消息:"+message);     }         public void sendMessage(String message){         for(WebSocket  webSocketSet : webSocketSet){             try{                 webSocket.sesion.getBasicRemote().sendText(message);                 }catch(Exception e){                     e.printStackTrace();                   }           }                 } }

27、异常使用心得:

27.1 根据不同业务定义对应的异常(要继承 RuntimeException),行参类型使用枚举 27.2 有异常直接抛出 27.3 处理:对于返回json的接口,使用@ControllerAdice,@ExceptionHandler(value=定义好的异常类.class) 对于返回页面的路由,使用try{}catch(){}的方法进行捕获

28、mybatis的使用:

28.1 引入依赖:mybatis-spring-boot-starter(1.2.0) 28.2 在主启动类中添加@MapperScan(basePackages="com.imooc.dataobject.mapper")//mapper接口所在的包 28.3 在com.imooc.dataobject.mapper包下创建接口类 28.4 设置日志级别为:trace logging.level.com.imooc.dataobject.mapper = trace//否则就无法看到正确查询时的sql语句   28.5.1 map方式写入 @Insert("insert into product_category(category_name,category_type) values(#{categoryName,jdbcType=VARCHAR},#{categoryType,jdbcType=INTEGER})") int insertByMap(Map<String,Object>); 28.5.2 对象方式写入 @Insert("insert into product_category(category_name,category_type) values(#{categoryName},#{categoryType})") int insertByObject(ProductCategory productCategory); 28.5.3 查询 @Select("select * form product_category where category_type = #{categoryType}") @Results({     @Result(colum = "category_id",property= "categoryId"),     @Result(colum = "category_name",property= "categoryName"),     @Result(colum = "category_type",property= "categoryType")     }) ProductCategory findBycategoryType(Integer categoryType); 28.5.4 某些字段更新 @Update("update product_category set category_name =#{categoryName} where category_type=#{categoryType}") int updateByCategoryType(@Parm("categoryName") String categoryName,@Parm("categoryType")Integer categoryType ); 28.5.5 对象更新 @Update("update product_category set category_name =#{categoryName} where category_type=#{categoryType}") int updateByObject(ProductCategory productCategory ); 28.5.6 删除 @Delete("delete from product_category  where category_type=#{categoryType}") int deleteByCategoryType(Integer categoryType); 28.6 xml例子: 28.6.1 在resources 下建一个mapper包,再在mapper下建xml文件 28.6.2 配置mybatis.mapper-locations=classpath:mapper/*.xml

29、JPA 与 MyBatis都要注意:

29.1 建表时用sql,不用JPA建表 29.2 表与表之间的关系使用软关联,慎用@oneToMany和@ManyToOne

30、压测工具:Apache ab 

30.1 ab -n 100 -c 100 网址 (-n 100 表示 100 个请求,-c 100 表示 100 个并发) 30.2 ab -t 60 -c 100 网址 (-t 60 表示 60秒内不停地请求,-c 100 表示 100 个并发)

31、并发:

31.1 使用Synchronized 可以保证数据线程安全,但速度会慢,无法做到细粒度控制,只适合单点的情况 31.2 使用redis分布式锁(因为redis是单线程的):用到的命令:SETNX(key已存在就什么也不做,若key不存在就更新),GETSET(先取出值,将更新) 31.2.1 加锁/解锁方法: @Component @Slf4j public class RedisLock {     @Autowired     private StringRedisTemplate redisTemplate;       /**      * 加锁      * @param key      * @param value 当前时间+超时时间      * @return      */     public  boolean lock(String key,String value){         if(redisTemplate.opsForValue().setIfAbsent(key,value)){             return true;         }         //currentValue =A ,两个线程的value都是B,其中一个线程拿到锁         String currentValue = redisTemplate.opsForValue().get(key);         //如果锁过期         if(!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue)<System.currentTimeMillis()){             //获取上一个锁的时间             String oldValue = redisTemplate.opsForValue().getAndSet(key,value);             if(!StringUtils.isEmpty(oldValue) &&oldValue.equals(currentValue)){                 return true;             }         }         return false;     }       public void unlock(String key,String value){         try{             String currentValue = redisTemplate.opsForValue().get(key);             if(!StringUtils.isEmpty(currentValue) && currentValue.equals(value)){                 redisTemplate.opsForValue().getOperations().delete(key);             }         }catch (Exception e){             log.error("【redis分布式锁】解锁异常,{}",e.getMessage());         }     } }

32、缓存:

32.1 启动类加@EnableCaching//如果不存在,就引入依赖spring-boot-starter-cache 32.2 对要使用缓存的方法加@Cacheable(cacheNames="product",key="123") 32.2.1 属性cacheNames:缓存key的前缀 32.2.2 属性key:缓存key,可以动态赋值key="#参数",eg:key = "#productId" 32.2.3 属性condition:条件判断,成立时才缓存,eg:condition = "#productId.length()&10" 32.2.4 unless:条件,如果不,eg:unless = "#result.getCode!=0)//只有在返回结果的code为0时才进行缓存,#result可以代替方法的返回对象 32.3 对触发更新缓存的方法加@CachePut(cacheNames="product",key="123")//会将key相同的(包括前缀)的缓存值更新(要求方法的返回对象与使用缓存的方法的返回对象相同) 32.4 对触发清空缓存的方法加@CacheEvict(cacheNames="product",key="123")//会将key相同的(包括前缀)的缓存清空(方法的返回对象可以与使用缓存的方法的返回对象不同) 32.5 对类加@CacheConfig(cacheNames="product")//这个类的方法如果使用缓存,则前缀都为product 32.6 注意:要缓存的对象一定继承可序列化类

33、项目部署

33.1 多环境配置:application-dev.yml application-prod.yml  application.yml(spring.profiles.active=dev)//默认是选择dev 33.2 打包 mvn clean packsge -Dmaven.test.skip=true 33.3 临时启动 java -jar -Dserver.port=8080 -Dspring.profiles.active=prod sell.jar 33.4 后台启动 nohup java -jar -Dserver.port=8080 -Dspring.profiles.active=prod sell.jar && /data/logs/didafenqi/didafenqi-api/log.out & 33.5 service方式启动 33.5.1内容:sell.service(放在/etc/systemd/system/下) [Unit] Description=sell After=syslog.target network.target   [Service] Type=StringRedisTemplate   ExecStart=/usr/bin/java -jar -Dserver.port=8080 -Dspring.profiles.active=prod sell.jar ExecStop=/bin/kill -15 $MAINPID   User=root Group=root   [Install] WantedBy=multi-user.target   33.5.2启动命令 systemctl start sell 33.5.3关闭命令 systemctl stop sell 33.5.4开机启动 systemctl enable sell 33.5.5取消开机启动 systemctl disable sell

标签:category,product,缓存,spring,boot,key,微信,categoryType,public
From: https://www.cnblogs.com/anquing/p/17603513.html

相关文章

  • SpringBoot 整合 redis-阿里云发送短信
    pom<dependencies><!--阿里云短信--><dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-core</artifactId><version>4.5.16</version>......
  • Spring-1-透彻理解Spring XML的必备知识
    学习目标能够说出Spring的体系结构能够编写IOC-DI快速入门思考:为什么学习Spring而不是直接学习SpringBoot1Spring介绍思考:我们为什么要学习Spring框架?工作上面Java拥有世界上数量最多的程序员最多的岗位需求与高额薪资95%以上服务器端还是要用Java开发专业角度简化开发,降低企......
  • docker部署项目,涉及springboot\tomacat\nginx\es
    sudoapt-getinstalldocker-ce=5:20.10.6~3-0~debian-bullseyedocker-ce-cli=5:20.10.6~3-0~debian-bullseyecontainerd.iodocker部署项目信息:--172.17.0.1   172.16.22.401、docker部署tomcatdockerrun-d --namestock-admin--restartalways-p81:8080-e"TZ......
  • 微信小程序页面跳转方法总结
    在我们日常的开发过程中,跳转页面是每个项目中必有的需求,包括监听返回按钮,回到指定页面,在小程序中页面跳转即页面路由页面栈框架以栈的形式维护了当前的所有页面。当发生路由切换的时候,页面栈的表现如下:getCurrentPages()函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,第一......
  • Spring Authorization Server (十)自定义异常
    在前面的篇章中,我们在请求认证服务器的交互过程去中,如果出现了异常,则服务器响应给客户端的信息格式非常不友好,我们希望服务器在发生异常时,将异常信息按照固定的json格式返回给客户端,这时需要我们来自定义异常,我们需要将异常进行捕获,然后按照我们定义的格式输出。那么本篇,我们就来介......
  • @SpringBootTest
     1.学会使用Test,让自己的代码不再有bug——@SpringBootTest的妙用 https://baijiahao.baidu.com/s?id=1760961522946985249&wfr=spider&for=pc2.SpringBootTest人类使用指南https://zhuanlan.zhihu.com/p/111418479  3.解析“@ExtendWith注解“https://blog.csdn......
  • 微信小程序中获取用户信息、用户手机号
    1、小程序中获取用户信息、用户手机号等,属于敏感操作,需要用户主动触发,即:<buttonopen-type="getPhoneNumber"onGetPhoneNumber="handleGetPhoneNumberButtonClick">一键登录</button>上面的伪代码是获取用户手机号的操作,点击按钮会第一时间触发半屏弹窗让用户授权获取手......
  • 方便在非spring管理环境中获取bean的spring工具类
    spring工具类方便在非spring管理环境中获取beanimportorg.springframework.aop.framework.AopContext;importorg.springframework.beans.BeansException;importorg.springframework.beans.factory.NoSuchBeanDefinitionException;importorg.springframework.beans.facto......
  • SpringBoot-3 拦截器注入配置
    如果拦截器加载的时间点在Spring的上下文初始化之前,导致注入的值为null,您可以尝试以下两种解决方法:使用@PostConstruct注解:在拦截器中使用@PostConstruct注解标记一个初始化方法,在该方法中手动获取配置值,并进行相应的处理。这样可以确保在拦截器初始化完成后,配置值已经被正确加......
  • bootstrap-fileinput组件遇到的问题
    使用bootstrap-fileinput在进行上传的时候发现了一个问题,由于上传的可能是csv的文件那么这个时候当我们点击选择文件的时候他就会在网页上重新进行一个下载由于在断点的时候发现他是访问了blob的一个地址这个进行一个图片的显示。由于生成csv的文件地址访问了就直接下载了所以需要......