springboot需要回炉,和之前的java一样

对的,找时间好好看看spring全家

前后端交互,跨域问题

config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package cn.sdadgz.web_springboot.config;


import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.allowedHeaders("*")
.exposedHeaders("*")
.allowCredentials(true); // cookies
}
}

拦截器

继承mvc

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class WebAppConfigurer implements WebMvcConfigurer {

@Override
public void addInterceptors(InterceptorRegistry registry) {
// 可添加多个
registry.addInterceptor(new TestFilter()).addPathPatterns("/**");
}

....
}

HandlerInterceptor拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class TestFilter implements HandlerInterceptorAdapter {
private final Logger logger = LoggerFactory.getLogger(TestFilter.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
logger.info("request请求地址path[{}] uri[{}]", request.getServletPath(),request.getRequestURI());
//request.getHeader(String) 从请求头中获取数据
//从请求头中获取用户token(登陆凭证根据业务而定)
Long userId= getUserId(request.getHeader("H-User-Token"));
if (userId != null && checkAuth(userId,request.getRequestURI())){
return true;
}
//这里的异常是我自定义的异常,系统抛出异常后框架捕获异常然后转为统一的格式返回给前端, 其实这里也可以返回false
throw new FastRuntimeException(20001,"No access");
}

/**
* 根据token获取用户ID
* @param userToken
* @return
*/
private Long getUserId(String userToken){
Long userId = null;
return userId;
}

/**
* 校验用户访问权限
* @param userId
* @param requestURI
* @return
*/
private boolean checkAuth(Long userId,String requestURI){
return true;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {}
}

注入

注入为空

PostConstruct,不够优雅

我也不知道为啥,cv的废物

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Component // 必须加,老忘
public class UserBan {

// 他自己
static UserBan userBan;

// 自动装配
@Resource
UserMapper userMapper;

@PostConstruct //通过@PostConstruct实现初始化bean之前进行的操作
public void init() {
userBan = this; // 不知道为什么,我是废物
}

// 如何调用
public void getTheFuckOut(String username,
HttpServletRequest request) {

LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getName, username);
// 使用::他自己.他里面的自动装配.方法
List<User> users = userBan.userMapper.selectList(wrapper);
}
}

优雅至极的方法

SpringUtil,别人那里复制的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package cn.sdadgz.web_springboot.utils;

import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
* <p>
* 废物本物,我和大佬的区别,就在这简单的几行中,面向cv编程
* </p>
*
* @author sdadgz
* @since 2023/2/15 01:07
*/
@Component
public class SpringUtil implements ApplicationContextAware {

private static ApplicationContext applicationContext;

@Override
public void setApplicationContext(@NotNull ApplicationContext applicationContext) {
SpringUtil.applicationContext = applicationContext;
}

//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}

//通过name获取 Bean.
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}

//通过class获取Bean.
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}

//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
1
2
// 大佬牛逼,真正的知道自己多废物了
private static final IUserService userService = SpringUtil.getBean(IUserService.class);

乱码,忘了使用场景了

1
2
3
4
5
6
7
8
9
@Bean
public HttpMessageConverter<String> responseBodyConverter() {
return new StringHttpMessageConverter(StandardCharsets.UTF_8);
}

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(responseBodyConverter());
}

获取ip

一代,零代是个demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 获取ip
public static String getIp(HttpServletRequest request) {
//目前则是网关ip
String ip = "";
log.info("访问者ip:{}", ip);
if (request != null) {
ip = request.getHeader("X-FORWARDED-FOR");
if (ip == null || "".equals(ip)) {
ip = request.getRemoteAddr();
}
}

return ip;
}

浅浅的研究了一下

代理服务器自定义的头中描述的ip,系与代理服务器直接连接的ip,例如nginx

request.getHeader(“[arg]”);

与springboot直接连接的ip

request.getRemoteAddr();

最终

去springboot端口,采用请求头传递ip

数据库时区

1
url: jdbc:mysql://sdadgz.cn:3307/website?useSSL=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai

异步

1
2
3
4
// 加config里吧,我更喜欢一劳永逸
@EnableAsync
// 标注他的方法会异步,这可能是句废话
@Async

缓存

1
2
3
4
5
6
7
8
9
10
11
12
// 这个加配置类上
@EnableCaching

// 这个加类上
@CacheConfig(cacheNames = "ipBanCache")

// 这个加方法上
@Cacheable
@CacheEvict(allEntries = true)

// 缓存不生效问题
ipBanService.blacklist(ip); // 不要直接调用方法,用service调

前端传时间过来

1
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)

url转义