前言:springboot整合mybatis、swagger、redis、thymeleaf-shiro、异步、定时任务以及mail邮件发送
项目结构:
一、整合mybatis
1、准备测试数据
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`age` int(10) NULL DEFAULT NULL,
`pwd` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`perms` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '张三', 45, '123456', 'user:add');
INSERT INTO `user` VALUES (2, '张三丰', 88, '123456', 'user:add');
INSERT INTO `user` VALUES (3, '郡主', 28, '888888', 'user:add');
INSERT INTO `user` VALUES (6, '李四', 33, '666666', 'user:add,user:update');
SET FOREIGN_KEY_CHECKS = 1;
2、导入依赖(所有的)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--redis整合-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.4.4</version>
</dependency>
<!--mail邮件发送-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>2.4.5</version>
</dependency>
<!--shiro整合spring的包-->
<!--<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.7.1</version>
</dependency>-->
<!--
Subject:用户
SecurityManager:管理所有用户
Realm:连接数据
-->
<!--整合mybatis连接数据库-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--thymeleaf-shiro整合-->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<!--shiro整合spring的包-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.7.1</version>
</dependency>
<!--Thymeleaf 基于3.x(2.x的会报错)-->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
<!--shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.1</version>
</dependency>
<!--logging-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
</dependency>
<!--swagger整合springboot-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3、创建pojo类
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel("用户实体类") //此处是swagger的用法
@Component //表示这是组件
public class User implements Serializable {
//controller的返回值为此实体类,则此实体类便会被扫描到swagger中
@ApiModelProperty("用户id") //此处是swagger的用法
private int id;
private String name;
private int age;
private String pwd;
private String perms;
}
4、创建mapper接口类
@org.apache.ibatis.annotations.Mapper //这个注解表示这是一个mybatis的mapper类
@Repository
public interface UserMapper {
List<User> getList();
User findByName(String name);
}
5、创建service接口类
public interface UserService {
List<User> getList();
User findByName(String name);
}
6、创建service接口实现类
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
@Override
public List<User> getList() {
return userMapper.getList();
}
@Override
public User findByName(String name) {
return userMapper.findByName(name);
}
}
7、创建controller类
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/findList")
@ResponseBody
public Object findList(){
return userService.getList();
}
@RequestMapping("/user")
@ResponseBody
public User getUser(){
return new User();
}
@ApiOperation("根据用户名查找用户")
@RequestMapping("/findByName")
@ResponseBody
public String findByName(@ApiParam("用户名") String name){
return "findByName";
}
}
8、创建实体类的mapper映射文件
<?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="com.springboot.mapper.UserMapper">
<select id="getList" resultType="user">
select * from user
</select>
<select id="findByName" resultType="user" parameterType="String">
select * from user where name = #{name}
</select>
</mapper>
9、创建application.properties配置文件
#mybatis配置
mybatis.type-aliases-package=com.springboot.pojo
mybatis.mapper-locations=classpath:mapper/*.xml
10、创建log4j.properties日志配置文件
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n
# General Apache libraries
log4j.logger.org.apache=WARN
# Spring
log4j.logger.org.springframework=WARN
# Default Shiro logging
log4j.logger.org.apache.shiro=INFO
# Disable verbose logging
log4j.logger.org.apache.shiro.util.ThreadContext=WARN
log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN
二、整合swagger
1、导入依赖包(此处忽略)
2、创建配置类,并开启swagger功能
@Configuration
@EnableSwagger2 //开启swagger2
public class SwaggerConfig {
//配置了swagger的docket的bean实例
@Bean
public Docket docket(Environment environment){
//获取设置的swagger项目环境
Profiles profiles = Profiles.of("dev","test");
//通过environment.acceptsProfiles判断是否处在自己设置的环境中
boolean flag = environment.acceptsProfiles(profiles);
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
//.groupName("测试") //分组,多个分组可以新建多个Docket实例
//.enable(flag) //是否开启swagger功能,false为关闭,true为开启
.select()
//RequestHandlerSelectors配置要扫描接口的方式
//.apis(RequestHandlerSelectors.any())
//.apis(RequestHandlerSelectors.withClassAnnotation(RequestMapping.class))
//过滤扫描什么路径
//.paths(PathSelectors.ant("/ces/**"))
.build();
}
//配置swagger信息apiInfo
public ApiInfo apiInfo(){
//作者信息
Contact contact = new Contact("my", "http://127.0.0.1", "");
return new ApiInfo(
"my test",
"Api Documentation",
"1.0",
"urn:tos",
contact,
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList<VendorExtension>());
}
}
3、在application.properties配置文件中设置环境
#环境设置
spring.profiles.active=dev
4、访问swagger页面
在浏览器中输入 http://localhost:8080/swagger-ui.html 访问
三、整合redis
1、导入依赖包(此处忽略)
2、在application.properties配置文件中配置
#配置redis
spring.redis.host=localhost
spring.redis.port=6379
3、创建配置类
//自定义redisTemplate模板
@Configuration
public class RedisConfig {
//固定模板,在企业中可以直接使用
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
// 我们为了自己开发方便,一般直接使用 <String, Object>
RedisTemplate<String, Object> template = new RedisTemplate();
template.setConnectionFactory(factory);
// Json序列化配置
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new
Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// String 的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
4、测试
@Autowired
RedisTemplate redisTemplate;
@Test
public void test(){
redisTemplate.opsForValue().set("name1","你好");
String name = (String)redisTemplate.opsForValue().get("name1");
System.out.println(name);
}
四、整合thymeleaf-shiro
1、导入依赖(此处忽略)
2、创建shiro.ini文件,并放到resources目录下
[users]
# user 'root' with password 'secret' and the 'admin' role
root = secret, admin
# user 'guest' with the password 'guest' and the 'guest' role
guest = guest, guest
# user 'presidentskroob' with password '12345' ("That's the same combination on
# my luggage!!!" ;)), and role 'president'
presidentskroob = 12345, president
# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'
darkhelmet = ludicrousspeed, darklord, schwartz
# user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'
lonestarr = vespa, goodguy, schwartz
# -----------------------------------------------------------------------------
# Roles with assigned permissions
#
# Each line conforms to the format defined in the
# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc
# -----------------------------------------------------------------------------
[roles]
# 'admin' role has all permissions, indicated by the wildcard '*'
admin = *
# The 'schwartz' role can do anything (*) with any lightsaber:
schwartz = lightsaber:*
# The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
# license plate 'eagle5' (instance specific id)
goodguy = winnebago:drive:eagle5
3、创建自定义Realm类
public class UserRealm extends AuthorizingRealm {
@Autowired
UserServiceImpl userService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权 =》 doGetAuthorizationInfo");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获取当前登录的对象
Subject subject = SecurityUtils.getSubject();
User user = (User)subject.getPrincipal();
info.addStringPermission(user.getPerms());
return info;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了认证 =》 doGetAuthenticationInfo");
//用户名、密码~ 数据库中取
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
User user = userService.findByName(token.getUsername());
if (user == null){
return null; //抛出异常 UnknownAccountException
}
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
session.setAttribute("loginUser",user);
return new SimpleAuthenticationInfo(user,user.getPwd(),"");
}
}
4、创建Shiro配置类
@Configuration
public class ShiroConfig {
//ShiroFilterFactoryBean:3
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器,关联创建的 DefaultWebSecurityManager
bean.setSecurityManager(defaultWebSecurityManager);
/**
* Shiro内置的过滤器
* anon:无需认证就能访问
* authc:必须认证才能访问
* user:必须拥有记住我功能才能访问
* perms:必须拥有对某个资源的访问权限才能访问
* role:拥有某个角色的权限才能访问
*/
//添加shiro的内置过滤器
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
/* filterChainDefinitionMap.put("/user/add","anon");
filterChainDefinitionMap.put("/user/update","authc");*/
//授权,正常情况下,没有授权会跳转到没有授权的页面
filterChainDefinitionMap.put("/user/add","perms[user:add]");
//拦截
filterChainDefinitionMap.put("/user/**","authc");
bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
//设置未授权页面
bean.setUnauthorizedUrl("/unauthor");
//设置登录的请求
bean.setLoginUrl("/toLogin");
return bean;
}
//DefaultWebSecurityManager:2
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联自定义的realm对象
securityManager.setRealm(userRealm);
return securityManager;
}
//创建realm对象,需要自定义:1
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
//整合 thymeleaf-shiro
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
}
5、创建controller类
@Controller
public class ShiroController {
@RequestMapping({"/","/index"})
public String index(Model model){
model.addAttribute("msg","hello shiro");
return "index";
}
@RequestMapping("/user/add")
public String add(){
return "user/add";
}
@RequestMapping("/user/update")
public String update(){
return "user/update";
}
@RequestMapping("/toLogin")
public String login(Model model){
model.addAttribute("msg","登录失败");
return "user/login";
}
@RequestMapping("/login")
public String login(String username,String password,Model model){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);
} catch (UnknownAccountException uae) {
model.addAttribute("msg","用户名不存在");
return "user/login";
} catch (IncorrectCredentialsException ice) {
model.addAttribute("msg","密码错误");
return "user/login";
}
return "index";
}
@RequestMapping("/unauthor")
@ResponseBody
public String unauthor(){
return "用户未授权,无法访问";
}
}
6、创建html页面,整合thymeleaf-shiro
1、index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>首页</h1>
<div th:if="${session.loginUser == null} ">
<a th:href="@{/toLogin}">登录</a>
</div>
<h2 th:text="${msg}"></h2>
<div shiro:hasPermission="user:add">
<a th:href="@{/user/add}">add</a>
</div>
<div shiro:hasPermission="user:update">
<a th:href="@{/user/update}">update</a>
</div>
</body>
</html>
2、login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>登录</h1>
<hr/>
<p th:text="${msg}" style="color: red"></p>
<form th:action="@{/login}" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="text" name="password"/><br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
3、add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
add
</body>
</html>
4、update.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
update
</body>
</html>
五、异步
1、创建controller类调用异步方法
@Controller
public class AsyncController {
@Autowired
private AsyncServiceImpl asyncService;
@RequestMapping("/async")
public String async(){
asyncService.async();//调用异步方法
return "index";
}
}
2、创建serviceImpl类实现异步方法
@Service
public class AsyncServiceImpl {
//告诉springboot此方法是异步方法
@Async
public void async() {
try {
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}
System.out.println("这是异步任务");
}
}
3、在springboot启动类中开启异步功能
@SpringBootApplication
@EnableAsync //开启异步任务
public class Springboot04Application {
public static void main(String[] args) {
SpringApplication.run(Springboot04Application.class, args);
}
}
六、定时任务
1、创建定时任service务实现类
@Service
public class SchedulingServiceImpl {
//cron : 秒 分 时 日 月 周几
@Scheduled(cron = "0 * * * * 0-7")
public void scheduling(){
System.out.println("定时任务执行了");
}
}
2、在springboot启动类中开启定时任务
@SpringBootApplication
@EnableAsync //开启异步任务
@EnableScheduling //开启定时任务
public class Springboot04Application {
public static void main(String[] args) {
SpringApplication.run(Springboot04Application.class, args);
}
}
七、mail邮件发送
1、导入依赖包(此处忽略)
2、修改application.properties配置文件
#mail邮件发送设置
spring.mail.username=141xxxxx@qq.com
spring.mail.password=nvrpclgtypxxxx
spring.mail.host=smtp.qq.com
#开启邮件加密验证(QQ)
spring.mail.properties.mail.smtp.ssl.enable=true
3、测试
@Autowired
JavaMailSenderImpl javaMailSender;
/**
* 简单邮件发送
*/
@Test
void contextLoads() {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setSubject("这是测试");
simpleMailMessage.setText("这是测试的内容");
simpleMailMessage.setTo("141xxxxx@qq.com");
simpleMailMessage.setFrom("141xxxxx@qq.com");
javaMailSender.send(simpleMailMessage);
}
/**
复杂邮件发送
*/
@Test
void contextLoads1() throws MessagingException {
//一个复杂的邮件
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
//组装
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
helper.setSubject("这是复杂邮件");
helper.setText("<p style='color:red'>这是复杂邮件的内容</p>",true);
//附件
helper.addAttachment("1.png",new File("C:\\Users\\Desktop\\苏宁售后服务流程.png"));
helper.addAttachment("接口开发.txt",new File("C:\\Users\\Desktop\\接口开发.txt"));
helper.setTo("141xxxxxx@qq.com");
helper.setFrom("141xxxxx@qq.com");
javaMailSender.send(mimeMessage);
}
完成!!!