SpringBoot

Spring-boot

Maven国内镜像

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

</mirrors>

yaml配置文件

通过yaml实现注入属性

User类

1
2
3
4
5
6
7
8
9
10
package com.example.demo.helloworld;

import lombok.Data;

@Data
public class User {
private String name;
private int id;
private String pwd;
}

Users类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.Date;
import java.util.List;
import java.util.Map;

/*ConfigurationProperties的作用:
* 将yaml配置文件中每一个属性的值映射到这个组件中
* 只有这个组件是容器中的组件时才会
*/
@ConfigurationProperties(prefix = "users")
@Data
public class Users {
private String name;
private String pwd;
private List<Object> lists;
private Map<String,Object> maps;
private User user;
private Date date;
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.example.demo;

import com.example.demo.helloworld.User;
import com.example.demo.helloworld.Users;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class DemoApplicationTests {

//将Users这个类加载到容器中
@Autowired
private Users users;
@Test
void contextLoads() {
System.out.println(users);
}

}

application.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server:
port: 8080
users:
name: 陈卓
pwd: 991220
lists:
- code
- music
- wmm
maps: {cz: 991220,wm: 991222}
date: 2019/12/14
user:
name: 王苗苗
id: 1805050226
pwd: 991222

JSR303校验

@Validated

Constraint 详细信息
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(value) 被注释的元素必须符合指定的正则表达式

Hibernate Validator 附加的 constraint

Constraint 详细信息
@Email 被注释的元素必须是电子邮箱地址
@Length 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range 被注释的元素必须在合适的范围内

配置文件优先级

file: ./config/

file:./

classpath: ./config/

classpath: /

多环境配置文件

yaml模块化

1
2
3
4
选择激活dev的配置
spring:
profiles:
active: dev
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server:
port: 8081
spring:
profiles:
active: dev
---
server:
port: 8082
spring:
profiles: dev
---
server:
port: 8083
spring:
profiles: test

静态资源

resources>static(默认)>public

扩展SpringMVC

注解

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
@Controller

标识这个类是一个控制器

@RequestMapping

给控制器方法绑定一个uri

@ResponseBody

将java对象转成json,并且发送给客户端

@RequestBody

将客户端请求过来的json转成java对象

@RequestParam

当表单参数和方法形参名字不一致时,做一个名字映射

@PathVarible

用于获取uri中的参数,比如user/11的值

Rest风格的新api

@RestController = @Controller+ @ResponseBody
@GetMapping
@DeleteMapping
@PostMapping
@PutMapping

拦截器

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
package com.kuang.interceptor;

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

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

public class MyInterceptor implements HandlerInterceptor {

//在请求处理的方法之前执行
//如果返回true执行下一个拦截器
//如果返回false就不执行下一个拦截器
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("------------处理前------------");
return true;
}

//在请求处理方法执行之后执行
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("------------处理后------------");
}

//在dispatcherServlet处理后执行,做清理工作.
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("------------清理------------");
}
}

Mybatis

和Mybatis原本的方法几乎一致,配置文件在resources文件下存放。

mapper接口一定要加 @Mapper @Repository

添加数据源yml

1
2
3
4
5
6
7
8
9
10
11
12
13
spring: 
datasource:
url: jdbc:mysql://localhost:3306/dbname
username: root
password: xxxx
driver-class-name: com.mysql.jdbc.Driver

#开启驼峰映射
mybatis:
configuration:
map-underscore-to-camel-case: true #开启驼峰映射
mapper-locations: classpath:mybatis/mapper/*.xml #用来映射mapper对应的xml
type-aliases-package: com.example.demo2.pojo #扫描加载pojo包中的类

爬坑:

  1. 当使用实体类接收json对象时,不管数据传的是一个对象还是多个,都要加@Parme
  2. @PostMapping时,接收的json的实例对象参数前要加 @RequestBody
  3. 如果接收的类中属性有对象属性,必须json也对应对象属性
  4. 在开启驼峰映射时,如果实体类中属性没有进行驼峰转换,会导致select不到该属性,但insert,delet,update都会正常与数据库交互,只有select会发生此类问题

@RequestBody主要用来接收前端传递给后端的json字符串中的数据的,@RequestBody与@RequestParam()可以同时使用

注:一个请求,只有一个RequestBody;一个请求,可以有多个RequestParam。

注:当同时使用@RequestParam()和@RequestBody时,@RequestParam()指定的参数可以是普通元素、数组、集合、对象等等
参数的机制不变,只不过RequestBody 接收的是请求体里面的数据;而RequestParam接收的是key-value
里面的参数,所以它会被切面进行处理从而可以用普通元素、数组、集合、对象等接收)。
即:如果参数时放在请求体中,传入后台的话,那么后台要用@RequestBody才能接收到;如果不是放在请求体中的话,那么后台接收前台传过来的参数时,要用@RequestParam来接收,或则形参前什么也不写也能接收。

注:如果参数前写了@RequestParam(xxx),那么前端必须有对应的xxx名字才行(不管其是否有值,当然可以通过设置该注解的required属性来调节是否必须传),如果没有xxx名的话,那么请求会出错,报400。

注:如果参数前不写@RequestParam(xxx)的话,那么就前端可以有可以没有对应的xxx名字才行,如果有xxx名的话,那么就会自动匹配;没有的话,请求也能正确发送。
追注:这里与feign消费服务时不同;feign消费服务时,如果参数前什么也不写,那么会被默认是@RequestBody的。

如果后端参数是一个对象,且该参数前是以@RequestBody修饰的,那么前端传递json参数时,必须满足以下要求:

后端@RequestBody注解对应的类在将HTTP的输入流(含请求体)装配到目标类(即:@RequestBody后面的类)时,会根据json字符串中的key来匹配对应实体类的属性,如果匹配一致且json中的该key对应的值符合(或可转换为),这一条我会在下面详细分析,其他的都可简单略过,但是本文末的核心逻辑代码以及几个结论一定要看! 实体类的对应属性的类型要求时,会调用实体类的setter方法将值赋给该属性。

json字符串中,如果value为"“的话,后端对应属性如果是String类型的,那么接受到的就是”",如果是后端属性的类型是Integer、Double等类型,那么接收到的就是null。

json字符串中,如果value为null的话,后端对应收到的就是null。

如果某个参数没有value的话,在传json字符串给后端时,要么干脆就不把该字段写到json字符串中;要么写value时, 必须有值,null 或"“都行。千万不能有类似"stature”:,这样的写法
————————————————
版权声明:本文为CSDN博主「justry_deng」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/justry_deng/article/details/80972817

Shiro

Subject 用户

SecurityManager 管理所有用户

Realm 连接数据

导入

1
2
3
4
5
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.2</version>
</dependency>

开始

ShiroConfig(固定写法321步骤):

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
package com.example.demo.config;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

//ShiroFilterFactoryBean :第三步,拦截基本都在这里
@Bean
public ShiroFilterFactoryBean geShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);

//添加shiro内置过滤器
/*
* anon:无需认证就可以访问
* authc:必须认证才可以访问
* user:必须拥有 记住我 功能才可以
* perms:拥有对某个资源对权限才能使用
* role:拥有某个角色权限才能访问
*/
//拦截
Map<String, String> filterMap = new LinkedHashMap<>();

//授权
filterMap.put("/admin/*","perms[admin]"); //访问带有admin下的资源必须权限中带有admin的字符

filterMap.put("/hello","authc"); //必须登录过后才能访问页面

//设置过滤器
bean.setFilterChainDefinitionMap(filterMap);
//设置登陆页面
bean.setLoginUrl("/login");

return bean;
}

//DefaultWebSecurityManger :第二步
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("peopleRealm") PeopleRealm peopleRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联Realm
securityManager.setRealm(peopleRealm);
return securityManager;
}

//创建 realm 对象 需要自定义类:第一步,认证在这里
@Bean
public PeopleRealm peopleRealm(){
return new PeopleRealm();
}
}

举例,用户Realm类:

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
package com.example.demo.config;

import com.example.demo.mapper.PeopleMapper;
import com.example.demo.pojo.People;
import org.apache.catalina.security.SecurityUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

public class PeopleRealm extends AuthorizingRealm {

@Autowired
private PeopleMapper peopleMapper;

//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了PeopleRealm的授权方法");
//创建认证对象
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//info.addStringPermission("管理员");

//拿到当前登录的对象
Subject subject = SecurityUtils.getSubject();
People people =(People) subject.getPrincipal(); //拿到people对象,也是下面认证时SimpleAuthenticationInfo的第一个参数的内容

//设置当前用户的权限
info.addStringPermission(people.getPerms());

return info;
}

//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行了PeopleRealm的认证方法");

UsernamePasswordToken usertoken = (UsernamePasswordToken) token;

//连接数据库查询
People people = peopleMapper.selectPeople(usertoken.getUsername());
if (people == null)
return null;

//第一个参数表示shiro获取到到用户所有信息
return new SimpleAuthenticationInfo(people,people.getName(),"");
}
}

异步任务

@EnableAsync :在主程序中打开异步任务

@Async 注解:在方法上使用,表示该方法为异步方法

0%