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转义

mybatis-plus入门

maven配置

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
<!--    sql    -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.15</version>
</dependency>
<!-- generator -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.9</version>
</dependency>

代码生成器

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
47
48
49
50
51
52
53
54
55
56
57
package cn.sdadgz.common;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.Collections;

/**
* <p>
* 废物本物
* </p>
*
* @author sdadgz
* @since 2023/2/15 21:51:54
*/
public class Generator {
public static void main(String[] args) {
// src 输出目录
String outputDir = "D:\\工具\\编程\\idea\\java工作区\\springcloudalibaba\\seata\\src\\main\\java";
// resources 输出目录
String mapperOutputDir = "D:\\工具\\编程\\idea\\java工作区\\springcloudalibaba\\seata\\src\\main\\resources"
+ "\\mapper";
// 父项目包名
String packagePath = "cn.sdadgz";

// 表名
String tableName = "user";

FastAutoGenerator.create("jdbc:mysql://sdadgz.cn:3307/spring-cloud", "root", "123456")
.globalConfig(builder -> {
builder.author("sdadgz") // 设置作者
.enableSwagger() // 开启 swagger 模式
.disableOpenDir()//完成后不打开文件夹
// 指定输出目录
//直接右键复制项目根目录的绝对路径
.outputDir(outputDir);
})
.packageConfig(builder -> {
builder.parent(packagePath) // 设置父包名
// 设置mapperXml生成路径
//直接右键复制项目mapper文件夹的绝对路径
.pathInfo(Collections.singletonMap(OutputFile.xml, mapperOutputDir));
})
.strategyConfig(builder -> {
builder.addInclude(tableName)//设置表名
.entityBuilder() //entity前置,才能用lombok
.enableLombok() //使用lombok
.controllerBuilder()
.enableRestStyle() //restMapping注解
.mapperBuilder()
.enableMapperAnnotation(); // 开启mapper注解
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}

配置文件

哪天我要看不懂这个了,重开吧

1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
datasource:
url: jdbc:mysql://sdadgz.cn:3307/spring-cloud?useSSL=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
type: com.alibaba.druid.pool.DruidDataSource
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true
auto-mapping-behavior: full
type-aliases-package: cn.sdadgz.entity

springboot入门

java.boot

主程序

1
2
3
4
5
6
7
8
9
10
11
12
13
package cn.sdadgz.boot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MainApplication {

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

}

controller

注解:

1
2
3
4
@RestController		// 无页面
@Controller // 页面
@RequestMapping("[路径]")
@ResponseBody // 无页面

config

手动添加bean

1
2
3
4
5
6
7
8
9
@Configuration
public class MyConfig(){

@Bean // 方法名做组件id,对象里面放值
public User user01(){
return new User("张三",18);
}

}

自定义

拦截器config
1
2
3
4
5
6
7
8
9
10
11
@Configuration
public class adminWebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")
// 此时静态资源也被拦截,网站访问静态资源也会出现登录
.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**");

}
}

矩阵变量|converter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//矩阵变量生效用
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
//重写这个extend方法,在数据类型中额外添加自己定义的数据
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new GuiguconventerMessage());
}
};
}

converter 提交数据时

1660233269866

messageConverter 返回数据时

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
public class GuiguconventerMessage implements HttpMessageConverter<Person> {
@Override
public boolean canRead(Class<?> aClass, MediaType mediaType) {
return false;//不让被注释识别
}

@Override
public boolean canWrite(Class<?> aClass, MediaType mediaType) {
return true;
}

@Override
public List<MediaType> getSupportedMediaTypes() {
return MediaType.parseMediaTypes("application/x-guigu");
}

@Override
public Person read(Class<? extends Person> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
return null;
}

@Override
public void write(Person person, MediaType mediaType, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
//规定数据类型
String data = person.getName()+";"+person.getPassword()+";"+person.getAge();
OutputStream body = httpOutputMessage.getBody();
//将类型保存
body.write(data.getBytes());
}
}

@Configuration

  • proxyBeanMethods = false // 默认true,其他组件不依赖它时用false更快

@Import({})

  • {User.class,Pet.class} // 自动创建组件

@ConditionalOnBean(name = “[tom]”) // tom存在时创建组件,省略其他条件装配

@ImportResource(“classpath:beans.xml”) // 导入xml装配

@EnableConfigurationProperties(User.class) // 自动装配配置文件

pojo

注解:

@Component // 组件

@ConfigurationPeroperties(Prefix = “[mycar]”) // 配置文件自动装配

拦截器旧

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
package com.atguigu.springboot.demo2.interceptor;
//登录拦截器

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginInterceptor implements HandlerInterceptor {
// 执行之前
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
Object loginuser = session.getAttribute("loginuser");
if(loginuser != null){
return true;
}else {
session.setAttribute("msg","请先登录");
// response.sendRedirect("/login");
request.getRequestDispatcher("/").forward(request,response);
//弹幕:因为前端页面是获取request域中数据,而重定向只能放session数据,为了不改变前端代码,所以这里改为请求转发
return false;

}
}
//执行之后
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
//页面渲染
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}

文件上传

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
@Controller
public class FormTestController {
@GetMapping("/form_layouts")
public String formLayout(){
return "form/form_layouts";
}


@PostMapping("/upload")
public String uploadForm(
@RequestParam("email") String email,
@RequestParam("username") String username,
@RequestParam("headerImg")MultipartFile headerImg,
@RequestParam("photos") MultipartFile [] photos
// 自动封装
){
// 获取文件测试
System.out.println("email:"+email+"username:"+username+"headering:"+headerImg.getSize()+"photos:"+photos.length);
// 保存文件
if(!headerImg.isEmpty()){
try {
// 获取文件名
String originalFilename = headerImg.getOriginalFilename();
headerImg.transferTo(new File("D:/cache/"+originalFilename));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// 保存一组图片
if (photos.length>0){
for (MultipartFile photo : photos) {
if(!photo.isEmpty()){
String originalFilename = photo.getOriginalFilename();
try {
photo.transferTo(new File("D:/cache/"+originalFilename));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}

return "main";
}
}

resources

application.properties|application.yaml

springboot配置文件 官网

开启页面表单的Rest功能

1
2
3
4
5
spring:
mvc:
hiddenmethod:
filter:
enabled: true #开启页面表单的Rest功能

开启请求参数内容协商模式

1
2
3
4
5
spring:
mvc:
contentnegotiation:
favor-parameter: true #开启请求参数内容协商模式

pom

导入JDBC

导入boot

1
2
3
4
5
6
7
8
9
10
11
12
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.2</version>
</parent>

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

yaml和properties自动提示

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

maven打包jar

1
2
3
4
5
6
7
8
9
10
11
12
<!--打包jar-->

<packaging>jar</packaging>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

maven重写boot配置

1
2
3
4
5
6
7
8
9
10
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>

<dependecies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependecies>

springboot+mybatis

导入pom

1
2
3
4
5
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>

配置文件properties|yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 配置mybatis规则
mybatis:
config-location: classpath:mybatis/mybatis-config.xml #全局配置文件位置
mapper-locations: classpath:mybatis/mapper/*.xml #sql映射文件位置

# 或

# 配置mybatis规则
mybatis:
# config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
configuration:
map-underscore-to-camel-case: true # 开启驼峰命名法

# 可以不写全局;配置文件,所有全局配置文件的配置都放在configuration配置项中即可

mapper

注解

  • @Mapper

我不会,长大后再学习

原生组件注入(Servlet,Filters,Listeners)

尚硅谷65p mybatisPlus下次从这p开始看,草,这会不看了

SpringBoot2核心技术与响应式编程 · 语雀 (yuque.com)

springMVC基础

maven安装

junit单元测试

1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>

spring-mvc

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.21</version>
</dependency>

不懂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>

配置文件

web.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">

<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

过滤器

1657779993902

json乱码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!--    json乱码-->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<!-- <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">-->
<!-- <property name="objectMapper">-->
<!-- <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">-->
<!-- <property name="failOnEmptyBeans" value="false"/>-->
<!-- </bean>-->
<!-- </property>-->
<!-- </bean>-->
</mvc:message-converters>
</mvc:annotation-driven>

springmvc-servlet.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
">

<context:component-scan base-package="cn.sdadgz.controller"/>
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>

java

controller例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package cn.sdadgz.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController{

@RequestMapping("/hello")
public String hello(Model model){
model.addAttribute("msg","sdadgz");
return "hello";
}
}

注解

1
2
3
4
5
6
7
8
9
10
// 写类上,spring托管
@Controller
// 写类上,类中方法只返回字符串
@RestController
// url
@RequestMapping("/hello")
// url 函数参数 (@PathVariable int a, @PathVariable int b, Model model)
@RequestMapping("/hello/{a}/{b}")
// 返回字符串(如:json)
@ResponseBody

其他

手动添加lib

project structure —–> artifacts —–> 加号,新建文件夹lib,加号,lib什么file,都勾上

拦截器

1658245028514

1658245065481

文件上传

1658315379939

1658315432944

1658317373113

注解

本来挺喜欢辣椒的,现在更喜欢了

maven安装

1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>

注解

  • @Data
  • @AllArgsConstructor
  • @NoArgsConstructor
  • @ToString
  • @EqualsAndHashCode 看不懂
  • @slf4j
  • @Accessors(chain = true) 不喜欢@AllArgsConstructor,就爱用链子
  • @Accessors(fluent = true) 不优雅

懒人很喜欢,谢

  • @Builder 里面的集合加@Singular(“add*”) 优雅
  • @SneakyThrows 睡觉不提示
  • @Synchronized 锁
  • @Cleanup 自动释放资源,这个很优雅
  • var 同js 不优雅
  • @FieldNameConstants 可替代
  • @RequiredArgsConstructor(onConstructor_ = @Autowired) 优雅

log4j基础

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/kuang.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

1657186000414

maven基础

配置文件

环境变量

MAVEN_HOME

%MAVEN_HOME%\bin

localRepository配置本地库

1
<localRepository>D:/tool/workspace/maven</localRepository>

mirrors配置阿里云镜像

1
2
3
4
5
6
7
8
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>

profiles使用jdk8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.complier.source>1.8</maven.complier.source>
<maven.complier.target>1.8</maven.complier.target>
<maven.complier.complerVersion>1.8</maven.complier.complerVersion>
</properties>
</profile>
</profiles>

依赖

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<dependencies>
<!-- 单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>

<!-- springmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.21</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.21</version>
</dependency>


<!-- json-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.9</version>
</dependency>

<!-- 不知道有没有用-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>

<!-- mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>

<!-- c3p0-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.5</version>
</dependency>

<!-- mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>

<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>

</dependencies>

build

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
 <!--在build中配置resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>

<!--springboot打包jar-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

mybatis基础

入门_MyBatis中文网

maven安装

mysql

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>

mybatis

1
2
3
4
5
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>

配置文件

java

[类名]Mapper.xml

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
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--接口路径-->
<mapper namespace="cn.sdadgz.dao.UserMapper">
<!--显示全部-->
<select id="getUserList" resultType="cn.sdadgz.pojo.User">
select * from mybatis.user
</select>
<!--查询指定-->
<select id="getUserById" parameterType="int" resultType="cn.sdadgz.pojo.User">
select * from mybatis.user where id = #{id}
</select>
<!--插入-->
<insert id="addUser" parameterType="cn.sdadgz.pojo.User">
insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd})
</insert>
<!--更新-->
<update id="updateUser" parameterType="cn.sdadgz.pojo.User">
update mybatis.user set name=#{name},pwd=#{pwd} where id = #{id}
</update>
<!--删除-->
<delete id="deleteUser" parameter="int">
delete from mybatis.user where id = #{id}
</delete>
</mapper>
  • id 调用时名字
  • resultType 返回值类型
  • parameterType 参数类型
resultMap
result

1657182916658

association(对象)
  1. property 对象名
  2. column 数据库名 向子查询传参用这个 column=”id = user_id”
  3. javaType 类名
  4. 嵌套增删改查 例:select

例:association(子查询) column传参

1657294027376

例:association-2

1657294812642

collection

ofType

例:collection

1657297461218

例:collection-2

1657298641599

utils工具类

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
package cn.sdadgz.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MybatisUtils {

private static SqlSessionFactory sqlSessionFactory;

static {
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
throw new RuntimeException(e);
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}

public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}

resources

mybatis-config.xml配置文件

  1. settings
    1. 配置_MyBatis中文网
  2. mappers
    1. mapper
      1. resource 指定xml
      2. class 指定class,接口必须和xml同名
      3. package 自动扫描,接口必须和xml同名
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
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

<!--里面可以放property定义值-->
<properties resource="db.properties"/>

<!--起别名-->
<typeAliases>
<!--指定类起别名-->
<typeAlias type="cn.sdadgz.pojo.User" alias="User"/>
<!--自动扫描默认首字母小写,再类前加注解@Alias("[别名]")自定义-->
<package name="cn.sdadgz.pojo"/>
</typeAliases>

<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>

<mappers>
<mapper resource="cn/sdadgz/dao/UserMapper.xml"/>
</mappers>
</configuration>

db.properties

1
2
3
4
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://49.232.139.28:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=[密码]

test

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
import cn.sdadgz.dao.UserDao;
import cn.sdadgz.pojo.User;
import cn.sdadgz.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;


public class UserDaoTest {

@Test
public void test(){
// 调用工具类
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 接口mapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 方法
List<User> userList = userMapper.getUserList();

for (User user : userList){
System.out.println(user);
}

sqlSession.close();
}
}

增删改必须提交事务

1
2
// 增删改后面加这个
sqlSession.commit();

万能map

1657178220228

注解

1657280158391

动态sql

where(set同理)通过trim实现

1657345036687

sql片段

1657349838943

choose(同switch)

  1. when(同case)
  2. otherwise(同default)

foreach

1657375512013

1657374707985

spring基础

maven安装

spirng-jdbc

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.21</version>
</dependency>

xml配置文件

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<!-->添加component</-->
<context:component-can base-package="cn.sdadgz"/>
<context:annotation-config/>

</beans>

mybatis配置

替换environments和mappers

configLocation替换configuration

1657613462195

1657613825383

bean创建对象

1
<bean id="[id]" class="[path]"></bean>
  • id=”[id]”
  • class=”[path]”
  • name=”[别名]” 多个用{逗号,空格,分号}分隔(引号内部)
  • scope=”[value]” prototype一人一个,默认都用一个
  • autowire=”[value]” 自动装配

property定义值

1
<property name="[name]" value="[value]"/>
  • name=”[name]”
  • value=”[value]”
  • ref=”[引用的bean对象]”
null
1
<null/>
array数组
1
2
3
<array>
<value></value>
</array>
list
1
2
3
<list>
<value></value>
</list>
map
1
2
3
<map>
<entry key="[key]" value="[value]"/>
</map>
set
1
2
3
<set>
<value></value>
</set>
Props原数据Properties
1
2
3
<props>
<prop key="[key]">[value]</prop>
</props>

constructor-arg有参构造

1
<constructor-arg index="[index]" value="[value]"/>
  • index=”[index]” 从0开始
  • name=”[name]”
  • value=”[value]”
  • ref=”[引用的bean对象]”

alias起别名

1
<alias name="[bean对象名]" alias="[别名]"></alias>

import导入

1
<import resource="[.xml文件]"/>

xml调用

获取ApplicationContext,spring容器

1
2
ApplicationContext [context] = new ClassPathXmlApplicationContext("[.xml文件]");
// 多个逗号隔开(引号外部)

操作容器

1
2
Object [name] = [context].getBean("[name]");
[类名] [name] = [context].getBean("[name]",类名.class);

java代替配置文件

1
2
3
4
5
6
// 类名前
@Configuration
@ComponentScan(cn.sdadgz) // 扫描指定包
@Import([其他配置文件].class) // 导入其他配置文件
// 方法名前
@bean

java调用配置文件

1
2
ApplicationContext [context] = new AnnotationConfigApplicationContext([config].class);
[类名] [name] = [context].getBean("[name]");

注解

1
2
3
4
5
6
7
8
9
10
@Autowired // 注解(byName实现)
@Autowired(required = false) // 可以为空
@Nullable // 用到再查
@Qualifier(value = "[name]") // 指定值
@Resource // 指定加(byName+byType)
@Component // 类名前,代替bean标签
@Repository // Component衍生
@service // 同上
@Controller // 同上
@Value([value]) // 注入值

动态代理

1
2
3
4
5
6
7
8
// 生成得到的代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),[被代理的类].getClass().getInterfaces,this);
}
// 处理代理实例,返回结果
public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
Object result = method.invoke([被代理的类],args);
}

用到再查

SqlSessionDaoSupport

1657614934864

mybatis事务

1657618289167

c命名p命名

aop

1657034767505

nginx基础

nginx安装(docker)

1
2
3
4
5
6
7
# 拉取镜像
docker pull nginx:[tag]
# run
$ docker run -d -p 443:443 -p 80:80 --name website --network website_net -v /www/www.sdadgz.cn/html/:/usr/share/nginx/html/ -v /www/www.sdadgz.cn/config/:/etc/nginx/ nginx
挂载数据卷
/usr/share/nginx/html/ # 默认html
/etc/nginx/ # 配置文件

配置文件

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
server {
# ssl证书配置
listen 443 ssl;
server_name sdadgz.cn;

# 证书路径
ssl_certificate /etc/nginx/ssl/sdadgz.cn_bundle.crt;
ssl_certificate_key /etc/nginx/ssl/sdadgz.cn.key;

# 不懂,复制的
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;

# 默认页
location / {
# 非根用alias,不知道为什么,反正能跑就完事了
root /usr/share/nginx/html;
index index.html index.htm;
}

# 官方模块download
location /download {
alias /etc/nginx/download;
autoindex on;
autoindex_exact_size off;
autoindex_format html;
autoindex_localtime on;
}
}

# http转https
server {
listen 80;
server_name sdadgz.cn;
return 301 https://$host$request_uri;
}

跨域

放location里

header里记得加上自定义请求头 ,全删了换成*吧

1
2
3
4
5
6
7
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

if ($request_method = 'OPTIONS') {
return 204;
}

重定向

那个逼东西自动重定向到当前url的/static/而不是/frp/static/妈的解决不了,索性/frp指向7500了

1
2
3
4
5
6
7
8
# 控制面板
location /frp {
return 301 http://$host:7500/;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Scheme $scheme;
}