springboot-03

自动注入

  1. yaml方式

    在类上加Component、ConfigurationProperties(perfix=yaml中的前缀)

  2. properties方式

    • 在类上加Component、PropertySource(value="classpath:properites位置")

    • 在相应字段上加@Value("${properties中配置的值}")

多环境配置

spring.profiles.active=dev选择生效配置

application-dev.propertiesapplication-test.properties

静态资源

Thymeleaf

1
2
3
4
5
6
7
8
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
1
2
3
4
5
6
7
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"

<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
  • 普通文本 th:文本元素="${变量}"或者[[ ${变量} ]]
  • 超链接 th:链接元素="@{变量}"
  • 遍历元素 th:each="item:${items}" th:text="${item}"
  • 国际化消息 th:文本元素="#{变量}"
  • ``逻辑判断 th:text=”${表达式 ? 结果}”`
  • 三元运算 th:text="${表达式?'选项1':'选项2'}"

自定义SpringMVC

  • 在自定义类上添加@Configuration注解
  • 实现WebMvcConfigurer接口
  • 写相关的类并注入到springboot中

springboot将类注入方法

@Bean

public 要注入的类 className(){

​ return new 要注入的类;

}

Mybatis

  • 在主类上添加@MapperScan("com.kuang.mapper")
  • 在mapper接口添加@Mapper
1
2
3
4
5
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
1
2
3
4
5
6
7
<?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">
<!--namespace属性:用于指定当前的映射文件和哪个接口文件进行映射,需要指定接口的文件路径,需要标注包的完整路径接口-->
<mapper namespace="com.kuang.mapper.UserMapper">
</mapper>
1
2
3
4
5
6
7
8
9
10
11
12
13
@Mapper
@Repository
public interface UserMapper {
List<User> queryUserList();

User queryUserById(Integer id);

void addUser(User user);

void updateUser(User user);

void deleteUser(Integer id);
}
1
2
3
4
5
6
7
8
9
10
11
@Controller
public class UserController {
@Autowired
private UserMapper userMapper;
@ResponseBody
@RequestMapping("/user/queryAll")
public List<User> queryUserList(){
return userMapper.queryUserList();
}
}

1
2
3
4
5
6
7
8
9
10
11
12
# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据源名称
spring.datasource.name=defaultDataSource
# 数据库连接地址
spring.datasource.url=jdbc:mysql://localhost:3306/springbootstudy?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=123456
#mybatis
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
#mybatis.type-aliases-package=com.kuang.pojo

SpringSecurity

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

授权

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//授权
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
//首页所有人可以访问,功能页面只有对应的人可以访问
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
//没有权限跳转登陆页面,会发送/login请求
http.formLogin().loginPage("/toLogin");
//注销
http.logout().
deleteCookies("remove").invalidateHttpSession(true)
.logoutSuccessUrl("/");
//记住我
http.rememberMe();

}
}

认证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

//认证,Springboot 2.1.X 可以直接使用
//密码编码:PsswordEncoder
//在Spring Security 5.0+ 新增了很多加密方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("zhangsan").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1")
.and()
.withUser("lisi").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2");
}
}

整合Thymeleaf

1
2
3
4
5
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
1
2
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
</html>

Shiro

快速开始

Apache Shiro Tutorial | Apache Shiro

pom.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
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
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>

<!-- This plugin is only to test run our little application. It is not
needed in most Shiro-enabled applications: -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<classpathScope>test</classpathScope>
<mainClass>Tutorial</mainClass>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.9.0</version>
</dependency>
<!-- Shiro uses SLF4J for logging. We'll use the 'simple' binding
in this example app. See http://www.slf4j.org for more info. -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
</dependencies>
log4j2.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
<Configuration name="ConfigTest" status="ERROR" monitorInterval="5">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="org.springframework" level="warn" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.apache" level="warn" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="net.sf.ehcache" level="warn" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.apache.shiro.util.ThreadContext" level="warn" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
shiro.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[users]
root = secret, admin
guest = guest, guest
presidentskroob = 12345, president
darkhelmet = ludicrousspeed, darklord, schwartz
lonestarr = vespa, goodguy, schwartz

# -----------------------------------------------------------------------------
# Roles with assigned permissions
# roleName = perm1, perm2, ..., permN
# -----------------------------------------------------------------------------
[roles]
admin = *
schwartz = lightsaber:*
goodguy = winnebago:drive:eagle5
Toturial
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
84
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Tutorial {

private static final transient Logger log = LoggerFactory.getLogger(Tutorial.class);

public static void main(String[] args) {
log.info("My First Apache Shiro Application");

Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);

// get the currently executing user:
Subject currentUser = SecurityUtils.getSubject();

// Do some stuff with a Session (no need for a web or EJB container!!!)
Session session = currentUser.getSession();
session.setAttribute("someKey", "aValue");
String value = (String) session.getAttribute("someKey");
if (value.equals("aValue")) {
log.info("Retrieved the correct value! [" + value + "]");
}

// let's login the current user so we can check against roles and permissions:
if (!currentUser.isAuthenticated()) {
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
token.setRememberMe(true);
try {
currentUser.login(token);
} catch (UnknownAccountException uae) {
log.info("There is no user with username of " + token.getPrincipal());
} catch (IncorrectCredentialsException ice) {
log.info("Password for account " + token.getPrincipal() + " was incorrect!");
} catch (LockedAccountException lae) {
log.info("The account for username " + token.getPrincipal() + " is locked. " +
"Please contact your administrator to unlock it.");
}
// ... catch more exceptions here (maybe custom ones specific to your application?
catch (AuthenticationException ae) {
//unexpected condition? error?
}
}

//say who they are:
//print their identifying principal (in this case, a username):
log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

//test a role:
if (currentUser.hasRole("schwartz")) {
log.info("May the Schwartz be with you!");
} else {
log.info("Hello, mere mortal.");
}

//test a typed permission (not instance-level)
if (currentUser.isPermitted("lightsaber:wield")) {
log.info("You may use a lightsaber ring. Use it wisely.");
} else {
log.info("Sorry, lightsaber rings are for schwartz masters only.");
}

//a (very powerful) Instance Level permission:
if (currentUser.isPermitted("winnebago:drive:eagle5")) {
log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. " +
"Here are the keys - have fun!");
} else {
log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
}

//all done - log out!
currentUser.logout();

System.exit(0);
}
}

Springboot

导入依赖
1
2
3
4
5
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.9.0</version>
</dependency>
shiro配置
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
package com.kuang.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.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

//ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
factoryBean.setSecurityManager(securityManager);

//添加过滤器
/*
aono: 无需认证就可以访问
authc: 必须认证了才可以访问
user: 必须拥有 记住我 功能才能访问
perms: 拥有对某个资源的权限才能访问
role: 拥有某个角色权限才能访问
*/
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/user/*","authc");
factoryBean.setFilterChainDefinitionMap(filterMap);

factoryBean.setLoginUrl("/toLogin");

return factoryBean;
}

//DefaultWebSecurity
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);

return securityManager;
}
//创建realm对象,需要自定义类
@Bean(name="userRealm")
public UserRealm userRealm(){
return new UserRealm();
}
}


认证授权
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 com.kuang.config;

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class UserRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String name = "root";
String password = "123456";

UsernamePasswordToken userToken = (UsernamePasswordToken)authenticationToken;

if(!userToken.getUsername().equals(name)){
return null;
}

return new SimpleAuthenticationInfo("",password,"");
}
}

mybatis

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

import com.kuang.pojo.User;
import com.kuang.service.UserServiceImpl;
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;

public class UserRealm extends AuthorizingRealm {
UserServiceImpl userService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Subject subject = SecurityUtils.getSubject();
User currentUser = (User) subject.getPrincipal();

//根据用户进行操作授权
//info.addObjectPermission();
return info;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken userToken = (UsernamePasswordToken)authenticationToken;

User user = userService.queryUserByName("userToken.getUsername()");


if (user==null){
return null;
}

return new SimpleAuthenticationInfo(user,user.getPassword(),"");
}
}

Thymeleaf

1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/com.github.theborakompanioni/thymeleaf-extras-shiro -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.1.0</version>
</dependency>

1
2
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">

Swagger

依赖
1
2
3
4
5
6
7
8
9
10
11
12
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</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
@Configuration
@EnableSwagger2
public class SwaggerConfig {

@Bean
public Docket docket(){
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());
}

private ApiInfo apiInfo(){
return new ApiInfo(
"Kuang Swagger Api",
"有朝一日,成为一个高手",
"1.0",
"https://zuoyenuandong.github.io/",
new Contact("kuang", "https://zuoyenuandong.github.io/", "1400584782@qq.com"),
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList());

}

}
访问链接

http://localhost:8080/swagger-ui.html

注释
  • ApiModel(""):在实体类上面添加注释
  • ApiModelProperty(""):在实体类字段添加注释
  • ApiOperation(""):方法添加注释
  • ApiParam(""):方法参数添加注释

任务

异步任务

  • 主类上添加@EnableAsync
  • 方法上添加@Async

邮件任务

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>

)

1
2
3
4
5
# 邮箱
spring.mail.username=1400584782@qq.com
spring.mail.password=pyprtzvykygyfffd
spring.mail.host=smtp.qq.com
spring.mail.properties.mail.smtp.ssl.enable=true
简单邮件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@SpringBootTest
class SpringbootStudy08JobApplicationTests {
@Autowired
JavaMailSenderImpl javaMailSender;
// 简单邮件
@Test
void contextLoads() {

SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setSubject("springboot mail service");
simpleMailMessage.setText("hello world");
simpleMailMessage.setTo("2597972416@qq.com");
simpleMailMessage.setFrom("1400584782@qq.com");
javaMailSender.send(simpleMailMessage);
}

}
复杂邮件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
void contextLoads2() throws MessagingException {

MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
messageHelper.setSubject("springboot mail service");
//可以传输html
messageHelper.setText("<p style='color:blue'>hello world</p>",true);
//添加附件
//messageHelper.addAttachment();
messageHelper.setTo("2597972416@qq.com");
messageHelper.setFrom("1400584782@qq.com");
javaMailSender.send(mimeMessage);

}

定时任务

TaskScheduler:任务调度者

TaskExecutor:任务执行者

EnableScheduling:开启定时任务

Scheduled:什么时候执行

1
2
3
4
5
6
7
8
@Service
public class ScheduledService {
//秒 分 时 日 月 周几
@Scheduled(cron = "0 * * * * 0-7")//任何时候的第0秒执行
public void hello(){
System.out.println("hello world");
}
}

Dobbo Zookeeper

准备

  • 下载zookeeperdubbo-admin
  • dubbo-admin打包成一个jar包mvn clean package -Dmaven.test.skip=true
  • dubbo-admin的端口号为7001
  • zookeeper的端口号为2181,默认用户名和密码都是root

springboot

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
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient -->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<!--解决依赖冲突-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.8</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>