00-杂

Mr.Home / 2023-08-28 / 原文

一、idea工具设置ctrl+鼠标中建改变字体大小

  1. settings

  2. editer,第一个选项卡

    image-20221129220918785

idea中文输入法失效的解决办法

1、点击菜单help->Edit Custom VM Options

image-20221210144705983

2、最后一行,追加:

-Drecreate.x11.input.method=true

image-20221210144816350

idea变量使用不同的颜色

说明:每个主题可单独配置

image-20230110161700224

二、vue下拉框参数校验

不会直接显示,在提交表单的时候,才会显示

image-20221129221135974

image-20221129221219901

三、JSON数据格式

JSON数据格式默认是在字符串里面的,但是纯数字,可以不加双引号 ,但是最终的结果还是字符串,数据库可以自动识别字符串数字,例如id="1",数据库可以识别为id=1

四、字体的安装

选中字体,右键安装即可

五、mysql-limit

limit后面的参数,不能是表达式,识别不了image-20221129222347245

六、js var修饰符会提升变量的声明作用域

console.log(temp);
var temp = 'hello';
//输出结果:undefine,不是报错,是没有赋值,相当于下面的语句
var temp;
console.log(temp);
temp = 'hello';

七、linux关机命令

shutdown -h now
halt
poweroff

八、客户端和服务端代码

看运行时的平台

九、spring的设计模式

实体类:单例模式

validator参数校验

Intager用notNULL,而不是notEmpty

十、建造者模式代码示例

外部类调用静态builder()方法初始化参数,并通过build方法返回外部对象实例,

private OAInfoService oaService;
private  MainUI mainUI;
private  FirstMenuUI  firstMenuUI;
private SecondMenuOneUI secondMenuOneUI;
private SecondMenuTwoUI secondMenuTwoUI;
private SecondMenuThreeUI secondMenuThreeUI;
//标志
private String flagChoiceOne = " ";
private String flagChoiceTwo  = " ";
private String flagChoiceThree = " ";

/**
 * 使用建造者模式代替上面的构造方法
 * */
public static class Builder {
    private OAInfoService oaService;
    private  MainUI mainUI;
    private  FirstMenuUI  firstMenuUI;
    private SecondMenuOneUI secondMenuOneUI;
    private SecondMenuTwoUI secondMenuTwoUI;
    private SecondMenuThreeUI secondMenuThreeUI;
    //标志
    private String flagChoiceOne = " ";
    private String flagChoiceTwo  = " ";
    private String flagChoiceThree = " ";
    /**
     * oaService必须通过参数赋值,三个标志看需要赋值
     * */
    public Builder oaService(OAInfoService oaService){
        this.oaService = oaService;
        return this;
    }
    public Builder flagChoiceOne(String flagChoiceOne){
        this.flagChoiceOne = flagChoiceOne;
        return this;
    }
    public Builder flagChoiceTwo(String flagChoiceTwo){
        this.flagChoiceTwo = flagChoiceTwo;
        return this;
    }
    public Builder flagChoiceThree(String flagChoiceThree){
        this.flagChoiceThree = flagChoiceThree;
        return this;
    }

    public OAConsleUI build(){
        //构建OAConsleUI对象
        OAConsleUI oaConsleUI = new OAConsleUI();
        oaConsleUI.oaService = this.oaService;
        oaConsleUI.flagChoiceOne = this.flagChoiceOne;
        oaConsleUI.flagChoiceTwo = this.flagChoiceTwo;
        oaConsleUI.flagChoiceThree = this.flagChoiceThree;
        oaConsleUI.mainUI = new MainUI(this.oaService);
        oaConsleUI.firstMenuUI = new FirstMenuUI(this.oaService);
        oaConsleUI.secondMenuOneUI = new SecondMenuOneUI(this.oaService);
        oaConsleUI.secondMenuTwoUI = new SecondMenuTwoUI(this.oaService);
        oaConsleUI.secondMenuThreeUI = new SecondMenuThreeUI(this.oaService);
        return oaConsleUI;
    }
}
/**
 * 通过静态方法提供一个构造器
 * */
public static Builder builder(){
    return new Builder();
}

11 spring-mvc项目添加web模块

右上角->设置按钮,编辑项目project-structture

image-20221208222751628

image-20221208222858192

生命周期

核心类: DispatchServlet

里面的核心方法:doService() -> doDispatch() ->获取handler和adapter

mappedHandler = getHandler(processedRequest);
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

通过反射调用方法,返回modelAndView

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

处理方法的参数

mav = invokeHandlerMethod(request, response, handlerMethod);
invocableMethod.invokeAndHandle(webRequest, mavContainer);

参数解析器会有缓存,第一次没有,避免每次否循环判断得到每个参数的解析器

处理链是一个类,里面有处理器、拦截器、跨域请求、实体类名

12 pom.xml中设置参数

声明版本号变量
<spring.version>版本号</spring.version>
使用变量
<version>${spring.version}</version>

13 url请求头参数

Content-Type:application/x-www-form-urlencoded
Content-Type:application/json
Content-Type:multipart/form-data

14 vue项目跨域请求传递给java后端的的seetionId是不一样的,默认axios没有发送cookies

15 java发送邮箱的工具类

发送邮箱需要的依赖

 <!--JavaMail基本包-->
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4.7</version>
        </dependency>
        <!--邮件发送的扩展包-->
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>

封装好的发送邮件的方法

  /**
     * 发送邮件
     *
     * @param emailHost     电子邮件主机
     * @param transportType 传输类型
     * @param fromUser      发件人签名
     * @param fromEmail     发件人电子邮件
     * @param authCode      发件人邮箱授权码
     * @param toEmail       收件人电子邮件
     * @param subject       邮件主题
     */
    public static void sendMail(String emailHost, String transportType,  String fromUser, String fromEmail, String authCode, String toEmail, String subject, String content, String contentHeader) throws UnsupportedEncodingException, MessagingException {

        //初始化默认参数
        Properties props = new Properties();
        props.setProperty("mail.transport.protocol", transportType);
        props.setProperty("mail.host", emailHost);
        props.setProperty("mail.user", fromUser);
        props.setProperty("mail.from", fromEmail);
        //获取Session对象
        Session session = Session.getInstance(props, null);
        //开启后有调试信息
        //session.setDebug(true);

        //通过MimeMessage来创建Message接口的子类
        MimeMessage message = new MimeMessage(session);
        //下面是对邮件的基本设置
        //设置发件人:
        //设置发件人第一种方式:直接显示:antladdie <antladdie@163.com>
        //InternetAddress from = new InternetAddress(sender_username);
        //设置发件人第二种方式:发件人信息拼接显示:name <antladdie@163.com>
        String formName = MimeUtility.encodeWord(fromUser) + " <" + fromEmail + ">";
        InternetAddress from = new InternetAddress(formName);
        message.setFrom(from);

        //设置收件人:
        InternetAddress to = new InternetAddress(toEmail);
        message.setRecipient(Message.RecipientType.TO, to);

        //设置抄送人(两个)可有可无抄送人:
       /* List<InternetAddress> addresses = Arrays.asList(new InternetAddress("1457034247@qq.com"), new InternetAddress("575814158@qq.com"));
        InternetAddress[] addressesArr = (InternetAddress[]) addresses.toArray();
        message.setRecipients(Message.RecipientType.CC, addressesArr);*/

        //设置密送人 可有可无密送人:
        //InternetAddress toBCC = new InternetAddress(toEmail);
        //message.setRecipient(Message.RecipientType.BCC, toBCC);

        //设置邮件主题
        message.setSubject(subject);

        //设置邮件内容,这里我使用html格式,其实也可以使用纯文本;纯文本"text/plain"
        message.setContent(content, contentHeader);

        //保存上面设置的邮件内容
        message.saveChanges();

        //获取Transport对象
        Transport transport = session.getTransport();
        //smtp验证,就是你用来发邮件的邮箱用户名密码(若在之前的properties中指定默认值,这里可以不用再次设置)
        transport.connect(props.getProperty("mail.host"), props.getProperty("mail.from"), authCode);
        //发送邮件
        transport.sendMessage(message, message.getAllRecipients());
    }

16 阿里云发送短信的工具类

pom依赖

	    <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>tea-openapi</artifactId>
            <version>0.2.5</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>dysmsapi20170525</artifactId>
            <version>2.0.23</version>
        </dependency>

封装好的工具类

public class Text {
    /**
     * 创建客户端
     * 使用AK&SK初始化账号Client
     *
     * @param accessKeyId     访问密钥id
     * @param accessKeySecret 访问密钥秘密
     * @return Client
     * @throws Exception 异常
     */
    public static com.aliyun.dysmsapi20170525.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                // 必填,您的 AccessKey ID
                .setAccessKeyId(accessKeyId)
                // 必填,您的 AccessKey Secret
                .setAccessKeySecret(accessKeySecret);
        // 访问的域名
        config.endpoint = "dysmsapi.aliyuncs.com";
        return new com.aliyun.dysmsapi20170525.Client(config);
    }

    /**
     * 得到发送短信请求
     *
     * @param phoneNumber   电话号码
     * @param signName      签名字
     * @param templateCode  模板代码
     * @param templateParam 模板参数
     * @return {@link com.aliyun.dysmsapi20170525.models.SendSmsRequest}
     */
    public static com.aliyun.dysmsapi20170525.models.SendSmsRequest getSendSmsRequest(String phoneNumber, String signName, String templateCode, String templateParam) {
        return new com.aliyun.dysmsapi20170525.models.SendSmsRequest()
                .setPhoneNumbers(phoneNumber)
                .setSignName(signName)
                .setTemplateCode(templateCode)
                .setTemplateParam(templateParam);
    }

    }

代码示例


//创建客户端对象
            Client client = Text.createClient("*","*");
            //创建连接对象
            SendSmsRequest sendSmsRequest = Text.getSendSmsRequest("15739","test","code","{\"code\":\"6666\"}");
            //发送短信,得到api对象
            SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, new RuntimeOptions());
            System.out.println("发送状态:" + sendSmsResponse.getStatusCode());

17 spring 2.6.3和swagger3.0冲突,@EnableOpenApi注解报空指针异常

swagger的maven依赖

用下面的版本可以不用降低sprign的版本

<!--        swagger依赖-->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.6.9</version>
        </dependency>

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
            <version>4.0.0</version>
        </dependency>

18 idea快速转换大小写

快捷键: ctrl + shift + u

插件: CamelCase , alt + shift + u ,驼峰式命名、帕斯卡命名、大写和小写互相循环转换

19 查看类继承图

快捷键: ctrl + alt + u

image-20221226104315352

20 判断是否为整数

整数 % 1 == 0

21 java多模块项目注意事项

  1. 模块之间的调用,例如调用工具类的模块时, 需要在入口处添加工具类包的路径,当前子模块项目默认扫描本项目,不会跨模块项目去扫描

image-20221226210543424

22 Windows查看指定端口被哪个进程占用

查看指定端口的占用情况

netstat -ano|findstr "端口号"

23 http请求类型

option:预检请求

24 Vue.config.js 配置报错 ValidationError: Invalid options object.

image-20230130193219818

25 spring-boot项目配置redis

需要2个配置文件

第一个实现基本缓存

package servlet_login_01.config;

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;

/**
 * @author 老九学堂@源小匠
 * @copyright 老九学堂@源小匠
 */
@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    RedisCacheConfiguration redisCacheConfiguration(RedisTemplate redisTemplate) {
        return RedisCacheConfiguration.defaultCacheConfig()
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getKeySerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()))
                .disableCachingNullValues()
                ;


    }
}

第二个 使用Jackson2JsonRedisSerialize 替换默认的jdkSerializeable序列化,便于在客户端查看数据

package servlet_login_01.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @author : Jia
 * @date : 2023/1/10 16:39:19
 */
@Configuration
@EnableCaching
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // 使用Jackson2JsonRedisSerialize 替换默认的jdkSerializeable序列化
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(om.getPolymorphicTypeValidator(),ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 字符串序列器
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

加了配置二后的效果

image-20230202201908717

26 NodeJS全局安装模块后,在js文件里面使用报错

配置环境变量

新建环境变量

NODE_PATH

值:你的全局模块的安装路径

D:\NodeJS\node_global\node_modules

image-20230210133347819

27 NodeJS解析jwt-token信息

const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
window = dom.window;
document = window.document;
XMLHttpRequest = window.XMLHttpRequest;
//使用js解析jwtToken信息
const token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJleHAiOjE2NzU5OTM5NDM1MzUsInVzZXJuYW1lIjoiYWRtaW4ifQ.DVLfhejhqVrgRA2WYVaAAsJpmqoZFeKv634D88b38Oae8frSaExbAQVyYclOPL5Scdy6kya_LKe8WaFYaER2fVudQARpr7pXmU0VbdyyCvo83Ws3xNKAAeb81C4Ka8drp6kHJep_bU49SaiKLVqEupt2H8ZjxxqZevAaafCrOUjONdJELYtMeVWz6ZrMvq-0ufFP6zTIhNYOJeFC8JKVTfd_TFsQIasjwhbFRmkcZOQN4SaUM9ZiQq1CYPYpUKpIhLCE8pPjzw1jYdhoVHyw_w1J4gfsoIOGdEpDxZ8RZbJjQX3tJCTKOy8NSlFVB-70zZyxS-hSwi_t1Tnz6gugjg";
let strings = token.split("."); //截取token,获取载体
var userinfo = JSON.parse(decodeURIComponent(encodeURIComponent(window.atob(strings[1].replace(/-/g, "+").replace(/_/g, "/")))));
console.log(userinfo)

28 cmd启动nginx

切换到当前nginx.exe目录下

启动命令

start nginx.exe

关闭nginx命令

nginx -s stop

重启Nginx

nginx -s reload

29 vwmare启动失败

无法打开内核设备"\.\Global\vmx86":系统找不到指定的文件。是否在安装VMware Workstation 后重新引导?

image-20230217134803183

30 匿名内部类反序列化失败

redis 不能反序列化匿内部类,或者强转失败

31 手动创建一个线程池

 //手动创建一个线程池
        threadPool = new ThreadPoolExecutor(2, 5,
                1L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());

32 mybatis自动生成代码

  @Autowired
    private DataSource dataSource;

    private String baseProjectPath;
    private String sourcePath;
    private String resourcePath;

    private DataSourceConfig.Builder dataSourceConfig;


    @BeforeEach
    void setUp() {
        baseProjectPath = System.getProperty("user.dir");
        sourcePath = new File(baseProjectPath, "src/main/java".replace("/", File.separator)).toString();
        resourcePath = new File(baseProjectPath, "src/main/resources".replace("/", File.separator)).toString();

        dataSourceConfig = new DataSourceConfig.Builder(dataSource)
                .dbQuery(new MySqlQuery())
                .typeConvert(new MySqlTypeConvert())
                .keyWordsHandler(new MySqlKeyWordsHandler())
        ;
    }

    @AfterEach
    void tearDown() {
    }


    @Test
    public void fastAutoGeneratorTest() {
        FastAutoGenerator.create(dataSourceConfig)
                // 设置全局配置
                .globalConfig(this::globalConfig)
                // 设置包配置
                .packageConfig(this::packageConfig)
                // 进行策略配置
                .strategyConfig(this::strategyConfig)
                .strategyConfig(this::strategyEntityConfig)
                .strategyConfig(this::strategyMapperConfig)
                .strategyConfig(this::strategyServiceConfig)
                .strategyConfig(this::strategyControllerConfig)
                .templateConfig(this::templateConfig)
                .execute();
        ;
    }

    /**
     * 进行全局配置
     *
     * @param builder
     */
    public void globalConfig(GlobalConfig.Builder builder) {
        builder
                // 禁用文件夹打开
                .disableOpenDir()
                // 启用swagger3的API注解
                .enableSpringdoc()
                // 设置作者
                .author("请书写自己的名字")
                .outputDir(sourcePath);
    }

    /**
     * 进行包配置
     *
     * @param builder
     */
    public void packageConfig(PackageConfig.Builder builder) {
        builder
                // 设置项目的根 root 包
                .parent("com.xuetang9.product.icsap.system.management")
                .entity("domain.entity")
                .mapper("mapper")
                .service("service")
                .serviceImpl("service.impl")
                .controller("web")
                .pathInfo(Collections.singletonMap(OutputFile.xml, resourcePath + "/mapper".replace("/", File.separator)));
    }

    /**
     * 进行全局的策略配置
     *
     * @param builder
     */
    public void strategyConfig(StrategyConfig.Builder builder) {
        builder.addInclude("system_resource", "system_role", "system_user", "system_role_resource", "system_user_role");
    }

    /**
     * 进行实体类的策略配置
     *
     * @param builder
     */
    public void strategyEntityConfig(StrategyConfig.Builder builder) {
        builder
                .entityBuilder()
//                // 设置实体类需要继承的公共父类的全路径类名
//                .superClass("com.xuetang9.product.icsap.system.management.domain.entity.BaseEntity")
//                // 公共的父类里面具有属性(实际填写的是公共列名)
//                .addSuperEntityColumns("id","create_time","update_time")
                // 自动填充的列和填充方式
                .addTableFills(
                        new Column("create_time", FieldFill.INSERT),
                        new Column("update_time", FieldFill.INSERT_UPDATE)
                )
                // 设置乐观锁的列名
                .versionColumnName("version")
                // 设置逻辑删除的列名
                .logicDeleteColumnName("is_deleted")
                // 禁用SerialVersionUID
//                .disableSerialVersionUID()
                // 设置主键的生成策略
                .idType(IdType.AUTO)
                // 启用ActiveRecord模式
//                .enableActiveRecord()
                // 启用生成字段名常量
                .enableColumnConstant()
                // 启用Lombok注解
                .enableLombok()
                // 启用链式模型
                .enableChainModel()
                // 启用移除字段的is前缀
                .enableRemoveIsPrefix()
                // 启用强制生成字段名注解
                .enableTableFieldAnnotation()
                // 设置表名和实体类名的映射方式
                .naming(NamingStrategy.underline_to_camel)
                // 设置列名和属性名的映射方式
                .columnNaming(NamingStrategy.underline_to_camel)
                // 设置生成的文件名
//                .formatFileName("%s")
                // 设置是否覆盖同名文件
                .enableFileOverride();
    }

    /**
     * 进行Mapper的策略配置
     *
     * @param builder
     */
    public void strategyMapperConfig(StrategyConfig.Builder builder) {
        builder.mapperBuilder()
                // 设置mapper继承的父类
                .superClass("com.baomidou.mybatisplus.core.mapper.BaseMapper")
                // 设置是否启用BaseResultMap
                .enableBaseResultMap()
                // 设置是否启用通用查询列的生成
                .enableBaseColumnList()
                // 设置Mapper类启用的注解
                .mapperAnnotation(Repository.class)
                // 设置生成的Mapper文件的名字
                .formatMapperFileName("%sMapper")
                // 设置生成的Mapper的xml文件的名字
                .formatXmlFileName("%sMapper")
                // 设置是否覆盖同名文件
                .enableFileOverride();
    }

    /**
     * 进行Service的策略配置
     *
     * @param builder
     */
    public void strategyServiceConfig(StrategyConfig.Builder builder) {
        builder.serviceBuilder()
                // 设置Service继承的父类
//                .superServiceClass("com.baomidou.mybatisplus.extension.service.IService")
//                .superServiceImplClass("com.baomidou.mybatisplus.extension.service.impl.ServiceImpl")
                .convertServiceFileName(entityName -> entityName + ConstVal.SERVICE)
                // 设置是否覆盖同名文件
                .enableFileOverride()
        ;
    }

    /**
     * 进行Controller的策略配置
     *
     * @param builder
     */
    public void strategyControllerConfig(StrategyConfig.Builder builder) {
        builder.controllerBuilder()
                // 启用驼峰转短横线连接
                .enableHyphenStyle()
                // 启用RestController风格
                .enableRestStyle()
                // 设置是否覆盖同名文件
                .enableFileOverride();
    }

    /**
     * 进行模板配置的策略配置
     *
     * @param builder
     */
    public void templateConfig(TemplateConfig.Builder builder) {
//        builder
//                .service("")
//                .serviceImpl("")
//                .controller("");
    }

33 idea多开springBoot项目

-Dserver.port=8094