杂乱无序(java框架)

134 阅读6分钟

spring定时器

主类加

@SpringBootApplication
@MapperScan("com.example.demo.dao")
@EnableScheduling
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

写个类表示定时执行

@Component
public class scheduledStart {

    @Resource
    private TCustomerServiceImpl customerService;
    
    // 执行周期
    @Scheduled(cron = "0/2 * * * * ?")
    public void start(){
        System.out.println("执行了");
        customerService.updateCustomerState();
    }
}

反射获取注解

@Around(value = "@annotation(com.example.demo.annotation.Purview)")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
    // 从session域中得到对象
    Object permissions = request.getSession().getAttribute("permissions");
    // 转为list集合
    List<String> list = MusterUtils.ObjectToListToString(permissions);
    AssertUtils.isTrue(null == permissions || list.size() == 0, "权限不足!");
    // 获取方法签名信息
    MethodSignature signature = (MethodSignature) pjp.getSignature();
    // 获取方法上的注解
    Purview purview = signature.getMethod().getDeclaredAnnotation(Purview.class);
    // 获取注解中的字段值
    String value = purview.value();
    // 不包含这个字段,返回权限不足
    AssertUtils.isTrue(!list.contains(value), "权限不足!");
    return pjp.proceed();
}

获取ip地址信息

并发使用,每个线程需要创建一个独立的 searcher 对象单独使用。

<dependency>
    <groupId>org.lionsoul</groupId>
    <artifactId>ip2region</artifactId>
    <version>2.7.0</version>
</dependency>

仅查询

public static void main(String[] args) throws Exception {
    // 数据地址
    String ipdb = "src/test/resources/ip2region.xdb";
    // 1. 创建searcher 对象
    Searcher searcher = Searcher.newWithFileOnly(ipdb);
    // 2. 查询
    String ip = "162.158.166.177";
    String search = searcher.search(ip);
    // 打印结果
    System.out.println("search = " + search); // 新加波
    // 4、关闭资源
    searcher.close();
}

获取详细的信息,需要使用淘宝ip库ip.taobao.com/outGetIpInf…

前后端传值

前端传数组,可以toString方法将数组转换字符串,自动带逗号,后端切割成数组

全局获得需要的资源

获取HttpServletRequest

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

记录一下,菜单控制角色

表格

create table sys_menu
(
    id        bigint auto_increment comment '自增ID'
        primary key,
    menu_name varchar(64)  not null comment '菜单名',
    perms     varchar(100) null comment '权限标识',
    parent_id int          null comment '父级菜单id'
)
    comment '菜单表' row_format = DYNAMIC;

代码

其中返回给前端的menvo类

public class MenuVo {
    private Integer id; // id
    private String parentMenu; //标签文本

    private List<MenuVo> subMenu; // 子集

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MenuVo menuVo = (MenuVo) o;
        return Objects.equals(id, menuVo.id) && Objects.equals(parentMenu, menuVo.parentMenu);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, parentMenu);
    }

    public MenuVo() {
    }
@Service
@Transactional
public class SysMenuServiceImpl implements SysMenuService {

    @Resource
    private SysMenuMapper sysMenuMapper;

    @Override
    public List<MenuVo> getTreeStructure() {
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(SysMenu::getParentId);
        // 查询到的所有菜单
        List<SysMenu> sysMenus = sysMenuMapper.selectList(wrapper);

        // 返回给前端的树状图集合
        ArrayList<MenuVo> vos = new ArrayList<>();
        // 存入父级ID,为了解决同级问题
        HashSet<Integer> integers = new HashSet<>();

        // 遍历查询
        for (SysMenu sysMenu : sysMenus) {
            // 如果没有权限字符,不需要进行添加
            if (StringUtils.isBlank(sysMenu.getPerms())) {
                continue;
            }
            MenuVo menuVo = handleMenu(sysMenu, sysMenus, new MenuVo(sysMenu.getId().intValue(), sysMenu.getMenuName()), integers, vos);
            if (menuVo != null) {
                vos.add(menuVo);
            }
        }
        return vos;
    }
    /**
     *
     * @param sysMenu      当前元素
     * @param sysMenus     所有元素
     * @param packageMenus 封装的元素
     * @param integers 判断重复的id集合
     * @param vos 返回前端的vo视图集合
     */
    private MenuVo handleMenu(SysMenu sysMenu, List<SysMenu> sysMenus, MenuVo packageMenus, HashSet<Integer> integers, ArrayList<MenuVo> vos) {
        integers.add(sysMenu.getId().intValue());
        // 创建集合存储子集信息
        ArrayList<MenuVo> newMenu = new ArrayList<>();
        // 如果为没有父级目录返回当前封装的集合
        if (sysMenu.getParentId() == null) return packageMenus;

        // 查出来父级的菜单信息
        SysMenu menu = findMenuById(sysMenu.getParentId(), sysMenus);
        // 如果未找到抛出异常
        AssertUtils.isTrue(menu == null, "数据库脏数据,请联系管理员!");

        // 将查找的元素放入集合
        MenuVo mv = new MenuVo();
        mv.setId(menu.getId().intValue());
        mv.setParentMenu(menu.getMenuName());
        // 添加时判断是否存在子元素(不断替换 packageMenus中的子元素信息)
        newMenu.add(packageMenus);
        mv.setSubMenu(newMenu);
        packageMenus = mv;

        // 要判断查出来的父级id是否已经存在过了
        if (integers.contains(menu.getId().intValue())) {
            addOwnedList(packageMenus, vos);
            return null;
        }
        integers.add(sysMenu.getParentId());


        // 继续遍历  没有父级菜单则返回
        return menu.getParentId() == null ? packageMenus : handleMenu(menu, sysMenus, packageMenus, integers, vos);
    }

    /**
     * 添加到对应的集合中
     */
    private void addOwnedList(MenuVo packageMenus, List<MenuVo> vos) {
        for (MenuVo vo : vos) {
            // 如果一致,则表示需要将 索引0的元素添加到 vos中对应的位置
            if (vo.getId().equals(packageMenus.getId())) {
                vo.getSubMenu().add(packageMenus.getSubMenu().get(0));
                return;
            } else {
                // 否则继续递归查询
                if (vo.getSubMenu() != null && vo.getSubMenu().size() != 0)
                    addOwnedList(packageMenus, vo.getSubMenu());
            }
        }
    }


    // 根据id找到对应菜单
    private SysMenu findMenuById(Integer id, List<SysMenu> sysMenus) {
        for (SysMenu sysMenu : sysMenus) {
            if (sysMenu.getId().intValue() == id) {
                return sysMenu;
            }
        }
        return null;
    }

SpingBoot 整合 druid

依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.16</version>
</dependency>

yml 配置

spring:
  datasource:
    druid:
      url: jdbc:mysql://localhost:3306/mu_xin
      username: root
      password: 1234
      initial-size: 5 # 初始连接数 (重要)
      min-idle: 5 # 最小空闲连接数 (重要)
      max-active: 20 # 最大活跃连接数 (重要)
      max-wait: 60000 # 获取连接的最大等待时间 (重要)
      time-between-eviction-runs-millis: 6000 # 定期验证连接的间隔时间 (重要)
      min-evictable-idle-time-millis: 300000 # 连接在池中最小生存的时间 (不重要)

      # Druid配置
      validation-query-timeout: 5 # 验证查询的超时时间 (重要)
      test-while-idle: true # 在连接空闲期间测试连接的有效性 (重要)
      test-on-borrow: false # 在从连接池中获取连接时是否进行测试 (不重要)
      test-on-return: false  # 在归还连接给连接池时是否进行测试 (不重要)
      pool-prepared-statements: true # 是否缓存预编译语句 (不重要)
      max-pool-prepared-statement-per-connection-size: 20 # 每个连接在缓存中可缓存的预编译语句的最大数量 (不重要)
      filters: stat,wall,log4j2 # Druid的过滤器列表 (不重要)

明文加密

依赖

<dependency>
    <groupId>org.mindrot</groupId>
    <artifactId>jbcrypt</artifactId>
    <version>0.4</version>
</dependency>
// 生成盐
String gensalt = BCrypt.gensalt();
// 密码加密
String hashpw = BCrypt.hashpw("123456", gensalt);
// 验证
BCrypt.checkpw("123456", "$2a$10$Ccvo9cVvXKDVmpL/Op0npOpTZQZmKBDcsuCUmCCgfDi1bz.no33xO");

克隆

BeanUtils.copyProperties(克隆源, 克隆到目标);

若依添加登录方式

项目需要添加新的登录方式,需要与平台登录隔离开

@PostMapping("/ar_login")
public AjaxResult ar_login(@NotBlank(message = "请求参数有误") String username) {

    HashSet<String> permiss = new HashSet<>();
    // 权限集合
    Collections.addAll(permiss, "ar_check:pending_approval:list", "ar_check:inspection:edit", "ar_check:device:query",
            "ar_check:defects:add");
    LoginUser loginUser = new LoginUser(user, permiss);
    SysUser user = new SysUser();
    user.setUserName("kun");
    loginUser.setUser(user);

    // 创建 Authentication 对象
    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
            loginUser, null, loginUser.getAuthorities());
    // 设置用户信息到 SecurityContext 中
    SecurityContextHolder.getContext().setAuthentication(authentication);

    AjaxResult ajax = AjaxResult.success();
    // 生成令牌
    String token = tokenService.createToken(loginUser);
    ajax.put(Constants.TOKEN, token);
    return ajax;
}

后台启动 jar

命令

javaw -jar xxxxxxx.jar

关闭

任务管理器打开详细信息, 找到 javaw 关闭

SpringBoot 关闭 web端口

  1. 去除 web 依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  1. 端口设置 -1,禁用 tomcat
server:
  port: -1
spring:
  main:
    web-application-type: none # 禁用

SpringBoot 整合Logback 日志

根目录文件 logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--
        CONSOLE :表示当前的日志信息是可以输出到控制台的。
    -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--输出流对象 默认 System.out 改为 System.err-->
        <target>System.out</target>
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度
                %msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %green(%5level) --- [%t] %c  [%thread] : %msg%n</pattern>
        </encoder>
    </appender>

    <!-- File是输出的方向通向文件的 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n)</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!--日志输出路径-->
        <file>C:/codeLigh/Lightning-data.log</file>
        <!--指定日志文件拆分和压缩规则-->
        <rollingPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--通过指定压缩文件名称,来确定分割文件方式-->
            <fileNamePattern>C:/codeLigh/Lightning-data2-%d{yyyy-MMdd}.log%i.gz</fileNamePattern>
            <!--文件拆分大小-->
            <maxFileSize>15MB</maxFileSize>
        </rollingPolicy>
    </appender>

    <!--

    level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
   , 默认debug
    <root>可以包含零个或多个<appender-ref>元素,标识这个输出位置将会被本日志级别控制。
    -->
    <!--    这里是输出配置,console表示在控制台输出,删除就没有了-->
    <root level="ALL">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </root>
</configuration>

依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

Spring Boot 打包 EXE

  1. 安装地址:exe4j.apponic.com/ (傻瓜式安装,一直下一步就行了)

激活:L-g782dn2d-1f1yqxx1rv1sqd

image.png

主界面:可以 open 打开加载的配置

image.png

选择 JAR 转 EXE

image.png

配置程序名称和存放路径

image.png

配置实例和应用信息

image.png

勾上 64 位系统

image.png

image.png

从不使用DPI

image.png

配置编码:在VM参数配置的地方加上:-Dfile.encoding=utf-8

image.png

选择 jar包

image.png

image.png

image.png

image.png

配置jre版本

image.png

这样打包,可以把jre打包,不用再按照jdk

image.png

image.png