-- 创造无限可能

当前mybaits-plus版本为3.5.3

springboot启动报错Bean named ‘ddlApplicationRunner’ is expected to be of type ‘org.springframework.boot.Runner’ but was actually of type ‘org.springframework.beans.factory.support.NullBean’

解决:在启动类加上方法

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


    /**
     * 解决:Bean named 'ddlApplicationRunner' is expected 的报错
     * @param ddlList
     * @return
     */
    @Bean
    public DdlApplicationRunner ddlApplicationRunner(@Autowired(required = false) List ddlList) {
        return new DdlApplicationRunner(ddlList);
    }

场景

实现

  1. 创建过滤器
    ```
    package com.bderp.config;

import com.bderp.common.TrimFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.DispatcherType;

@Configuration
public class FilterConfig {

/**
 * 去除参数头尾空格过滤器
 *
 * @return
 */
@Bean
public FilterRegistrationBean trimFilter() {
    System.out.println("============过滤=================");
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setDispatcherTypes(DispatcherType.REQUEST);
    registration.setFilter(new TrimFilter());
    registration.addUrlPatterns("/*");
    registration.setName("TrimFilter");
    registration.setOrder(1);
    return registration;
}

}

2. 创建过滤器类

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class TrimFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    filterChain.doFilter(new TrimHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse);
}

@Override
public void destroy() {

}

}

3. 创建请求参数过滤类

import com.bderp.utils.JsonTrimUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class TrimHttpServletRequestWrapper extends javax.servlet.http.HttpServletRequestWrapper {

private Map<String , String[]> params = new HashMap<>();

public TrimHttpServletRequestWrapper(HttpServletRequest request) {
    // 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似
    super(request);
    //将参数表,赋予给当前的Map以便于持有request中的参数
    this.params.putAll(request.getParameterMap());
    this.modifyParameterValues();
}
/**
 * 重写getInputStream方法  post类型的请求参数必须通过流才能获取到值
 */
@Override
public ServletInputStream getInputStream() throws IOException {
    System.out.println("data");
    System.out.println("aaaaaaaaaaaaS");
    //非json类型,直接返回
    if(!super.getHeader(HttpHeaders.CONTENT_TYPE).contains(MediaType.APPLICATION_JSON_VALUE)){
        return super.getInputStream();
    }
    //为空,直接返回
    String json = IOUtils.toString(super.getInputStream(), "utf-8");
    if (!StringUtils.hasLength(json)) {
        return super.getInputStream();
    }
    ByteArrayInputStream bis = null;
    try {
        bis = new ByteArrayInputStream(JsonTrimUtils.jsonTrim(json).toJSONString().getBytes());
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return new MyServletInputStream(bis);
}
/**
 * 将parameter的值去除空格后重写回去
 */
public void modifyParameterValues(){
    Set<String> set =params.keySet();
    Iterator<String> it=set.iterator();
    while(it.hasNext()){
        String key= it.next();
        String[] values = params.get(key);
        for (int i = 0; i < values.length; i++) {
            values[i] = values[i].trim();
        }
        params.put(key, values);
    }
}
/**
 * 重写getParameter 参数从当前类中的map获取
 */
@Override
public String getParameter(String name) {
    String[]values = params.get(name);
    if(values == null || values.length == 0) {
        return null;
    }
    return values[0];
}
/**
 * 重写getParameterValues
 */
@Override
public String[] getParameterValues(String name) {//同上
    return params.get(name);
}

class MyServletInputStream extends  ServletInputStream{
    private ByteArrayInputStream bis;
    public MyServletInputStream(ByteArrayInputStream bis){
        this.bis=bis;
    }
    @Override
    public boolean isFinished() {
        return true;
    }

    @Override
    public boolean isReady() {
        return true;
    }

    @Override
    public void setReadListener(ReadListener listener) {

    }
    @Override
    public int read() {
        return bis.read();
    }
}

}

4. 创建过滤工具类

package com.bderp.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONValidator;

import java.util.Iterator;
import java.util.Map;

/**

  • json工具类
  • @Version 1.0
    /
    public final class JsonTrimUtils {
    /*

    • 构造器
      */
      private JsonTrimUtils() {
      }

      /**

    • 去除json值前后空格
    • @param jsonStr jsonStr
    • @return
      */
      public static JSON jsonTrim(String jsonStr) throws Exception {
      System.out.println(“JSONValidator.Type.Object”);
      System.out.println(JSONValidator.Type.Object);
      System.out.println(JSONValidator.from(jsonStr).getType());
      System.out.println(JSONValidator.from(jsonStr).getType());
      if (JSONValidator.from(jsonStr).getType() == JSONValidator.Type.Object) {
       System.out.println("============data");
       System.out.println(jsonTrim(JSONObject.parseObject(jsonStr)));
       return  jsonTrim(JSONObject.parseObject(jsonStr));
      
      }
      //前后端联调传值类型不同,及早的暴露问题,避免隐藏问题。
      throw new Exception(“非JSON参数”);
      }

// /*
//
去除json值前后空格
// @param json jsonStr
//
@return
// */
// public static JSON jsonTrim(JSON json) throws Exception {
// if (json instanceof JSONObject) {
// return jsonTrim(json);
// } else if (json instanceof JSONArray) {
// jsonTrimArray((JSONArray) json);
// return json;
// }
// throw new Exception(“非JSON参数”);
// }

/**
 * 去除value的空格
 *
 * @param jsonObject jsonObject
 * @return
 */
public static JSONObject jsonTrim(JSONObject jsonObject) {
    Iterator<Map.Entry<String, Object>> iterator = jsonObject.entrySet().iterator();
    while (iterator.hasNext()) {
        Map.Entry<String, Object> next = iterator.next();
        Object value = next.getValue();
        if (value != null) {
            if (value instanceof String) {
                //清空值前后空格
                jsonObject.put(next.getKey(), ((String) value).trim());
            } else if (value instanceof JSONObject) {
                jsonTrim((JSONObject) value);
            } else if (value instanceof JSONArray) {
                jsonTrimArray((JSONArray) value);
            }
        }
    }

    return jsonObject;
}

/**
 * 清空JSONArray 值前后空格
 * @param array
 */
private static void jsonTrimArray(JSONArray array) {
    if (array.size() > 0) {
        for (int i = 0; i < array.size(); i++) {
            Object object = array.get(i);
            if (object != null) {
                if (object instanceof String) {
                    array.set(i, ((String) object).trim());
                } else if (object instanceof JSONObject) {
                    jsonTrim((JSONObject) object);
                } else if (object instanceof JSONArray) {
                    jsonTrimArray((JSONArray) object);
                }
            }
        }
    }
}

}

```

参考

https://blog.csdn.net/L_fly_J/article/details/120991367

场景

实现

  1. 创建过滤器
    ```
    package com.bderp.config;

import com.bderp.common.TrimFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.DispatcherType;

@Configuration
public class FilterConfig {

/**
 * 去除参数头尾空格过滤器
 *
 * @return
 */
@Bean
public FilterRegistrationBean trimFilter() {
    System.out.println("============过滤=================");
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setDispatcherTypes(DispatcherType.REQUEST);
    registration.setFilter(new TrimFilter());
    registration.addUrlPatterns("/*");
    registration.setName("TrimFilter");
    registration.setOrder(1);
    return registration;
}

}

2. 创建过滤器类

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class TrimFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    filterChain.doFilter(new TrimHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse);
}

@Override
public void destroy() {

}

}

3. 创建请求参数过滤类

import com.bderp.utils.JsonTrimUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class TrimHttpServletRequestWrapper extends javax.servlet.http.HttpServletRequestWrapper {

private Map<String , String[]> params = new HashMap<>();

public TrimHttpServletRequestWrapper(HttpServletRequest request) {
    // 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似
    super(request);
    //将参数表,赋予给当前的Map以便于持有request中的参数
    this.params.putAll(request.getParameterMap());
    this.modifyParameterValues();
}
/**
 * 重写getInputStream方法  post类型的请求参数必须通过流才能获取到值
 */
@Override
public ServletInputStream getInputStream() throws IOException {
    System.out.println("data");
    System.out.println("aaaaaaaaaaaaS");
    //非json类型,直接返回
    if(!super.getHeader(HttpHeaders.CONTENT_TYPE).contains(MediaType.APPLICATION_JSON_VALUE)){
        return super.getInputStream();
    }
    //为空,直接返回
    String json = IOUtils.toString(super.getInputStream(), "utf-8");
    if (!StringUtils.hasLength(json)) {
        return super.getInputStream();
    }
    ByteArrayInputStream bis = null;
    try {
        bis = new ByteArrayInputStream(JsonTrimUtils.jsonTrim(json).toJSONString().getBytes());
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return new MyServletInputStream(bis);
}
/**
 * 将parameter的值去除空格后重写回去
 */
public void modifyParameterValues(){
    Set<String> set =params.keySet();
    Iterator<String> it=set.iterator();
    while(it.hasNext()){
        String key= it.next();
        String[] values = params.get(key);
        for (int i = 0; i < values.length; i++) {
            values[i] = values[i].trim();
        }
        params.put(key, values);
    }
}
/**
 * 重写getParameter 参数从当前类中的map获取
 */
@Override
public String getParameter(String name) {
    String[]values = params.get(name);
    if(values == null || values.length == 0) {
        return null;
    }
    return values[0];
}
/**
 * 重写getParameterValues
 */
@Override
public String[] getParameterValues(String name) {//同上
    return params.get(name);
}

class MyServletInputStream extends  ServletInputStream{
    private ByteArrayInputStream bis;
    public MyServletInputStream(ByteArrayInputStream bis){
        this.bis=bis;
    }
    @Override
    public boolean isFinished() {
        return true;
    }

    @Override
    public boolean isReady() {
        return true;
    }

    @Override
    public void setReadListener(ReadListener listener) {

    }
    @Override
    public int read() {
        return bis.read();
    }
}

}

4. 创建过滤工具类

package com.bderp.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONValidator;

import java.util.Iterator;
import java.util.Map;

/**

  • json工具类
  • @Version 1.0
    /
    public final class JsonTrimUtils {
    /*

    • 构造器
      */
      private JsonTrimUtils() {
      }

      /**

    • 去除json值前后空格
    • @param jsonStr jsonStr
    • @return
      */
      public static JSON jsonTrim(String jsonStr) throws Exception {
      System.out.println(“JSONValidator.Type.Object”);
      System.out.println(JSONValidator.Type.Object);
      System.out.println(JSONValidator.from(jsonStr).getType());
      System.out.println(JSONValidator.from(jsonStr).getType());
      if (JSONValidator.from(jsonStr).getType() == JSONValidator.Type.Object) {
       System.out.println("============data");
       System.out.println(jsonTrim(JSONObject.parseObject(jsonStr)));
       return  jsonTrim(JSONObject.parseObject(jsonStr));
      
      }
      //前后端联调传值类型不同,及早的暴露问题,避免隐藏问题。
      throw new Exception(“非JSON参数”);
      }

// /*
//
去除json值前后空格
// @param json jsonStr
//
@return
// */
// public static JSON jsonTrim(JSON json) throws Exception {
// if (json instanceof JSONObject) {
// return jsonTrim(json);
// } else if (json instanceof JSONArray) {
// jsonTrimArray((JSONArray) json);
// return json;
// }
// throw new Exception(“非JSON参数”);
// }

/**
 * 去除value的空格
 *
 * @param jsonObject jsonObject
 * @return
 */
public static JSONObject jsonTrim(JSONObject jsonObject) {
    Iterator<Map.Entry<String, Object>> iterator = jsonObject.entrySet().iterator();
    while (iterator.hasNext()) {
        Map.Entry<String, Object> next = iterator.next();
        Object value = next.getValue();
        if (value != null) {
            if (value instanceof String) {
                //清空值前后空格
                jsonObject.put(next.getKey(), ((String) value).trim());
            } else if (value instanceof JSONObject) {
                jsonTrim((JSONObject) value);
            } else if (value instanceof JSONArray) {
                jsonTrimArray((JSONArray) value);
            }
        }
    }

    return jsonObject;
}

/**
 * 清空JSONArray 值前后空格
 * @param array
 */
private static void jsonTrimArray(JSONArray array) {
    if (array.size() > 0) {
        for (int i = 0; i < array.size(); i++) {
            Object object = array.get(i);
            if (object != null) {
                if (object instanceof String) {
                    array.set(i, ((String) object).trim());
                } else if (object instanceof JSONObject) {
                    jsonTrim((JSONObject) object);
                } else if (object instanceof JSONArray) {
                    jsonTrimArray((JSONArray) object);
                }
            }
        }
    }
}

}

```

今天拉取项目代码时,更新maven发现无法更新,然后查看错误发现pom.xml提示错误和警告信息

解决:根据提示,将项目所在目录添加进入系统的排除项中

需求:前端通过一个输入框,既可以查询学号又可以查询姓名
后端:通过或条件查询

//可以根据学号和姓名模糊搜索
        if(student.getStudentNumber() != null && !student.getStudentNumber().equals("")) {
            lqw.lambda().or(l -> {
                l.like(Student::getStudentNumber, student.getStudentNumber());
            }).or(l -> {
                l.like(Student::getName, student.getStudentNumber());
            });

            student.setStudentNumber(null);
        }

第一步

application.yml配置,添加两个数据配置

spring:
  datasource:
    primary:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/test001
      username: root
      password: 123456

    # 第二个数据库配置
    second:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/test002
      username: root
      password: 123456

第二步

添加一个数据库配置类

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

@Configuration
public class DataSourceConfig {

    @Primary
    @Bean(name = "primaryDataSource")
    @ConfigurationProperties(prefix="spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "secondDataSource")
    @ConfigurationProperties(prefix="spring.datasource.second")
    public DataSource secondDataSource() {
        return DataSourceBuilder.create().build();
    }
}

第三步

测试是否链接成功,尝试写入一条数据

    @GetMapping("test")
    public void test() throws Exception{

        // 创建数据库连接
        Connection connection = secondDataSource.getConnection();

        // 创建SQL语句
        String sql = "INSERT INTO tx_test (name) VALUES (?)";

        // 创建预编译语句
        PreparedStatement label = connection.prepareStatement(sql);


        // 执行语句
        label.setString(1, "4545");
        label.executeUpdate();

        // 关闭连接和语句
        label.close();
        connection.close();
    }

数据库写入成功

做好财富管理

当你银行卡有一定的钱后,你可以有选择的做自己喜欢的事情
你的焦虑通常来源于你的存款不足

  • 每个月的收入,每次保留一部分雷打不到存起来,存到不容易使用的地方
  • 刚毕业获得薪水后,容易冲动消费,买最新的手机,买任何自己想买的东西
  • 减少不必要的开支,比如租房可以多找几家,选便宜点的,可以讲价
  • 买东西前,估算下该物品是否是自己必要的,有没有其他可替代的方案,比如租借,比如不用也可以
  • 不要透支消费,透支消费只会让你越陷越深

做好个人的职业规划

  • 三年后自己想成为怎么样的人,拥有多少财富
  • 为了达到自己所期望的人,自己应该怎么办
  • 每天学习,每天进步一点点
  • 每天做一点于自己梦想有关的事情

了解人性

在学习,有学校的保护,可能不容易知道世界也有险恶的一面

  • 不要相信暴富的机会,暴富的机会都写在刑法里
  • 不要轻易相信他人,特别是涉及到利益交换的,比如购买贵重的东西

身体

  • 保持锻炼,你才能有机会触碰自己的未来
  • 保持良好的睡眠

场景一

项目越做越大,所有文件都在一个模块里面,不好管理
项目很大,由几个人开发,但是又统一发布,不好管控
在原来的系统上新增的模块功能,可能导致现有的模块出错

方案

分模块开发、maven集成和聚合

场景二

原有几个方法,需要在每个方法前面添加相同的功能,比如计时器

解决方案

AOP开发、切面编程

场景三

一个业务由多个修改数据表方法组成,一旦中间报错,所有修改操作都需要回滚

解决方案

事务管理

场景四

项目分布式部署,不方便进行权限验证

解决方案

JWT令牌验证

场景五

所有方法都需要验证权限后才能调用

解决方案

拦截器

@RequestParam
@RequestParam时如果前端没有传递参数,会报出一个异常警告提示,所以携带@RequestParam时参数是必传的

@GetMapping("/requestParm")
public R requestParm(@RequestParam Integer id){
    System.out.println("get带@RequestParam:"+id);
    return R.success(id);
}

异常提示:MissingServletRequestParameterException: Required request parameter 'id' for method parameter type Integer is not presen

不带@RequestParam时不管传不传参数,后端都不会报错,此时答应id的结果为null

@GetMapping("/requestParm")
public R requestParm(Integer id){
    System.out.println("get不带@RequestParam:"+id);

    return R.success(id);
}

实体类带上@RequestParam接收参数
同理,带上@RequestParam时,后端也是报了一个异常警告,接口状态码为400

@GetMapping("/requestParm")
public R requestParm(@RequestParam User user){
    System.out.println("get带@RequestParam:"+user.getId());

    return R.success(user);
}

实体类不带@RequestParam接收参数
接口没有报错,获取到的id参数为null

@GetMapping("/requestParm")
public R requestParm(User user){
    System.out.println("get不带@RequestParam:"+user.getId());

    return R.success(user);
}

总结:
1.用实体类接收参数时不能带上@RequestParam,否者接口会报错
2.如果是单个参数时,带上@RequestParam时前端不传参数就会报错,所以建议是不要带上@RequestParam,这样后端可以判断参数,如果参数必填的话应该是提示前端必传参数,而不是接口报错

所以不管是当个参数还是实体类接收参数,,可以都不要带上@RequestParam 。。。

@RestControllerAdvice注解是一个用于全局异常处理的注解,可以用来统一处理所有Controller层的异常。
@Order(index) //定义捕获错误的优先级

import com.bderp.controller.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import javax.servlet.http.HttpServletRequest;

@Slf4j
//@Order(2) //定义捕获错误的优先级
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler{

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public R handlerException(HttpServletRequest request, Exception e){

         //获取报错的控制器
         String controllerName = ex.getStackTrace()[0].getClassName();
         //获取报错行
         int lineNumber = ex.getStackTrace()[0].getLineNumber();

         //获取报错体
         StringWriter sw = new StringWriter();
         PrintWriter pw = new PrintWriter(sw);
         ex.printStackTrace(pw);
         String errorMessage = sw.toString();

         //写入日志文件
         //Logger.error(errorMessage);

        return R.error("错误了" + e.getMessage());
    }
}

引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

application.yml配置

spring:
    mail:
    #邮件发送配置
    host: smtp.qq.com
    port: 587
    username: xxx@qq.com
    password: xxx #邮件秘钥
    nickname: xxx
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true

添加一个发送邮件公共方法

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;

/**
 * 发送邮件公共方法
 */
@Controller
public class MailService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private JavaMailSender sender;


    @Value("${spring.mail.nickname}")
    private String nickname;


    @Value("${spring.mail.username}")
    private String from;


    /**
     * 发送纯文本的简单邮件
     * @param to
     * @param subject
     * @param content
     */
    public void sendSimpleMail(String to, String subject, String content){
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(to);
        message.setSubject(subject);
        message.setText(content);
        //邮件发送人
        message.setFrom(nickname+'<'+from+'>');

        try {
            sender.send(message);
            logger.info("邮件已经发送。");
        } catch (Exception e) {
            logger.error("异常!", e);
        }
    }

}

发送邮件通知


//发送邮件通知
mailService.sendSimpleMail("接收的邮件号", "邮件标题","邮件内容")

pom依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.7.0</version>
</dependency>

添加一个redis配置文件

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    @Value("${spring.redis.host}")
    private String redisHost;

    @Value("${spring.redis.port}")
    private int redisPort;

    @Value("${spring.redis.password}")
    private String redisPassword;

    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(redisHost, redisPort);
        config.setPassword(RedisPassword.of(redisPassword));
        return new JedisConnectionFactory(config);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        return template;
    }

application.yml 配置

redis:
    host: localhost
    port: 6379
    password:

读取、设置、删除

写入缓存,并设置10后过期
redisTemplate.opsForValue().set(key, value, 10, TimeUnit.SECONDS);

读取缓存
redisTemplate.opsForValue().get(key);

删除缓存
redisTemplate.delete(key);

使用场景

  1. 登录校验
  2. 请求数据预处理
  3. 过滤敏感字符

简单说明

  1. Filter 是 JavaEE 中 Servlet 规范的一个组件,位于包javax.servlet 中

过滤器使用

@Component
public class MyFilter implements Filter {
    //该方法在容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次,这个方法必须执行成功,否则过滤器会不起作用。
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Filter 前置");
    }
    // 容器中的每一次请求都会调用该方法, FilterChain 用来调用下一个过滤器 Filter。
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Filter 处理中");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("Filter 处理后");
    }
    // 当容器销毁 过滤器实例时调用该方法,一般在方法中销毁或关闭资源,在过滤器 Filter 的整个生命周期也只会被调用一次。
    @Override
    public void destroy() {
        System.out.println("Filter 后置");
    }
}

获取当前年份

//获取当前年份
Calendar cla = Calendar.getInstance();
int year = cla.get(Calendar.YEAR);

获取当前年月日

//获取当前年月日
Date date = new Date();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr = dateFormat.format(date);

@RequestParam:用于从请求参数中获取值,常用于GET请求,可以指定参数的名称和默认值。

@PathVariable:用于从URL路径中获取值,常用于RESTful风格的URL,可以指定参数的名称和默认值。

@RequestBody:用于从请求体中获取值,常用于POST请求,可以将请求体中的数据绑定到方法的参数上。

示例:

@PathVariable

接收链接上的参数
@PostMapping("/{currentPage}/{pageSize}")
@NoLoginRequired
public R text(@PathVariable Integer currentPage, @PathVariable Integer pageSize){

}

@RequestParam

接收get请求参数
@GetMapping("text")
public R text(@RequestParam Integer id){

}

@RequestBody

用HashMap接收json参数
@GetMapping("text")
public R text(@RequestBody HashMap<String, String> student){

    String studentId = student.get("studentId");
    String name = student.get("name");

}


用实体类接收json参数
@PostMapping("text")
public R text(@RequestBody Student student){

    String studentId = student.getStudentId;
    String name = student.getName;

}

问题

我们在做数据按日期汇总的时候,经常需要用到时间查询

场景

  1. 获取今日日期

    java.util.Date currentDate = new java.util.Date();
         // 创建SimpleDateFormat实例,指定日期格式
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
         // 格式化日期为字符串
         String todayDate = dateFormat.format(currentDate);
         return todayDate;
    
  2. 获取昨日日期

    java.util.Date currentDate = new java.util.Date();
          //格式化字符串
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
         Calendar calendar = Calendar.getInstance();
         calendar.add(Calendar.DAY_OF_MONTH, -1);     //减一天
         return dateFormat.format(calendar.getTime());
    
  3. 获取本周第一天日期

          //格式化字符串
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
         Calendar calendar = Calendar.getInstance();
         calendar.set(Calendar.DAY_OF_WEEK, 2);                //本周的第一天,写1获取到的是周日,2获取到的是周一
         return dateFormat.format(calendar.getTime());
    
  4. 获取本月第一天日期

    java.util.Date currentDate = new java.util.Date();
         // 创建SimpleDateFormat实例,指定日期格式
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
         // 格式化日期为字符串
         String todayDate = dateFormat.format(currentDate);
         return todayDate;
    

    总结

    /**
    * 数据导出工具类
    */
    public class DateUtils {
     //获取今日
     public String getTodayDate(){
         java.util.Date currentDate = new java.util.Date();
         // 创建SimpleDateFormat实例,指定日期格式
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
         // 格式化日期为字符串
         String todayDate = dateFormat.format(currentDate);
         return todayDate;
     }
     //获取昨日
     public String getYesterdayDate(){
         //格式化字符串
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
         Calendar calendar = Calendar.getInstance();
         calendar.add(Calendar.DAY_OF_MONTH, -1);     //减一天
         return dateFormat.format(calendar.getTime());
     }
     //获取本周第一天
     public String getThisWeekMonDay(){
         //格式化字符串
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
         Calendar calendar = Calendar.getInstance();
         calendar.set(Calendar.DAY_OF_WEEK, 2);                //本周的第一天,写1获取到的是周日,2获取到的是周一
         return dateFormat.format(calendar.getTime());
     }
     //获取本月第一天
     public String getThisMonthFirstDay(){
         //格式化字符串
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
         Calendar calendar = Calendar.getInstance();
         calendar.set(Calendar.DAY_OF_MONTH, 1);                //本周的第一天,写1获取到的是周日,2获取到的是周一
         return dateFormat.format(calendar.getTime());
     }
    }
    

问题

map是无序的

解决

  • 方法一:使用LinkedHashMap,保持插入的顺序

  • 方法二:使用TreeMap,按照Key的大小来排序;可以指定Comparator来确定key的大小

    Comparator<TopicNLPEnum> comp = (o1, o2) -> o2.getScore() - o1.getScore();
    Map<TopicNLPEnum, List<String>> map = new TreeMap(comp);
    

来源

https://www.jianshu.com/p/38f5a0ed0670

使用httClients发送post请求
`

/**
 * 使用httClients发送post请求
 * @param url 请求的url地址
 * @param list 需要发送的请求参数(需要一个ArrList)
 */
public String httpPost(String url, List list) throws Exception {

    CloseableHttpClient httpClient = null;
    CloseableHttpResponse response = null;

    try{
        httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);


        // 设置请求参数,可通过在接口传入
//            List<NameValuePair> list = new ArrayList<>();
//            list.add(new BasicNameValuePair("param1", "value1"));
//            list.add(new BasicNameValuePair("param2", "value2"));

        UrlEncodedFormEntity params = new UrlEncodedFormEntity(list, "UTF-8");

        //设置请求参数
        httpPost.setEntity(params);


        //发送http请求
        response = httpClient.execute(httpPost);

        //判断响应状态码
        if(response.getStatusLine().getStatusCode() == 200){
            //响应数据
            HttpEntity entity = response.getEntity();

            //将响应数据以字符串方式展示
            String html = EntityUtils.toString(entity, "UTF-8");

            return html;
        }

        //失败
        return "error";

    } catch (Exception exception){
        exception.printStackTrace();
        throw new Exception(exception.getMessage());
    }finally {
        try{
            //关闭资源
            httpClient.close();
            response.close();
        } catch (IOException e){
            //e.printStackTrace()方法介绍
            //当Java程序抛出异常时,它会在调用堆栈中创建一个异常对象并将其抛出。使用e.printStackTrace()方法可以打印出这个异常对象所在的调用堆栈,包括哪个类的哪个方法抛出了异常,以及异常被传播的路径。
            e.printStackTrace();
            throw new Exception(e.getMessage());
        }
    }

}`

发送get请求

public String httpGet(){

    //get请求直接写在地址拼接 (栗子:http://www.baidu.com?name=zhangsan&age=18)
    String url = "http://www.ttxtc.com";

    CloseableHttpClient httpClient = null;
    CloseableHttpResponse response = null;

    try{
        httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);

        //发送http请求
        response = httpClient.execute(httpGet);

        //判断响应状态码
        if(response.getStatusLine().getStatusCode() == 200){
            //响应数据
            HttpEntity entity = response.getEntity();

            //将响应数据以字符串方式展示
            String html = EntityUtils.toString(entity, "UTF-8");

            return html;
        }
    } catch (Exception exception){
        exception.printStackTrace();
    }finally {
        try{
            //关闭资源
            httpClient.close();
            response.close();
        } catch (IOException e){
            //e.printStackTrace()方法介绍
            //当Java程序抛出异常时,它会在调用堆栈中创建一个异常对象并将其抛出。使用e.printStackTrace()方法可以打印出这个异常对象所在的调用堆栈,包括哪个类的哪个方法抛出了异常,以及异常被传播的路径。
            e.printStackTrace();
        }
    }


}`

场景

现在需要获取List<Integer>中的某个值

List<String> list = new ArrayList<>();
list.add(10);
list.add(20);
list.add(30);

#报错语句
list.get(10)

报错

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IndexOutOfBoundsException: Index 13 out of bounds for length 1] with root cause

原因分析

尝试使用list.get(10)去获取值
list.get(10)实际获取的是索引为10的值,已经操作了list的长度,所以报错

解决方案

判断List对象是否包含某元素的方法有

  • list.contains(“A”);//不存在返回false
  • list.indexOf(“A”);//不存在则返回-1

场景

现在有一个map对象,需要遍历所有元素进行操作

方案

  1. for
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);

for (Map.Entry<String, Integer> entry : map.entrySet()) {
    String key = entry.getKey();
    Integer value = entry.getValue();
    System.out.println(key + ": " + value);
}
  1. forEach
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);

map.forEach((key, value) -> System.out.println(key + ": " + value));

场景

字符串数组转换成字符串的过程中,有时候需要给每个元素加上双引号

解决

strean流设置

List<String> list = Arrays.asList("张三", "李四", "王五");
String joined = list.stream()
    .map(s -> "\"" + s + "\"") // 在每个元素前后添加双引号
    .collect(Collectors.joining(", ")); // 用逗号分隔连接字符串

java如何向数组里添加元素

*注意:一般数组是不能添加元素的,因为他们在初始化时就已定好长度了,不能改变长度。

解决方案

1、先把数组转换成ArrayList数组,ArrayList数组是可变长度的,使用add方法添加元素
2、再把ArrayList数组转成一般数组

案例

Integer[] num={3,2};
List<Integer> list=new ArrayList(Arrays.asList(num));
list.add(5);
Integer[] numNew = new Integer[list.size()];

1、foreach是只读的,在取的时候数据不能变(包括修改,删除,添加等)。要避免这个问题,就应该使用for循环。
2、foreach属于迭代器,迭代循环。只能按序依次遍历完成,不支持中断行为。break和contine会报错,return虽然不会报错,但是不会返回。
3、for循环是可以中断循环(利用break语句或return语句,continue)
4、for可以认为指定关于循环的起点,foreach循环起点只能从0开始