SpringBoot 企业级简化开发(五)

简介: SpringBoot 企业级简化开发

SpringBoot 企业级简化开发(四)https://developer.aliyun.com/article/1469563


安全框架总结:

学习了Springsecurity和shiro之后,总结出一些学习方法

  1. 安全框架的核心思想都十分相似,授权,认证,防伪等
  2. 他们通常都有几个对象,如shiro中的subject,securityManager一样,
  3. 源码的注释写有方法使用的模版,我们可以通过下载源码去查看注释,
  4. Springsercurity和shiro的区别,两个我个人认为,除了一个基于Spring之外功能上两者几乎一致
  5. 使用的感受
  1. Spring Security基于Spring开发,项目中如果使用Spring作为基础,配合Spring Security做权限更加方便,而Shiro需要和Spring进行整合开发
  2. 感觉shiro没有类似于Spring Security那样的安全防护
  3. shiro不需要基于任何框架,依赖性低
  4. 个人认为:配置的麻不麻烦关键在于项目用不用Spring,我看大神们写博客都说shrio配置要更简单一些,但是简单的上手了两个安全框架之后,我觉得使用了Spring的项目上手security要比shiro简单的多,
  5. 还有个个人感想,帮助文档的阅读能力太重要了,学习和接触新技术在没有教程的情况下,文档的阅读能力决定了你的学习上限(个人中间有一段只照着官方文档学习,十分痛苦)
  1. 以上就是安全框架简单上手的全内容啦,

swagger

学习目标:

  • 了解Swagger的作用和概念
  • 了解前后端分离
  • 在SpringBoot中集成Swagger

Swagger简介

故事还是要从前后端分离讲起啊

前后端分离:VUE+SpringBoot 基本上都用这一套

后端时代:前端只用管理静态页面,html===》后端,使用模版引擎 jsp=》后端主力

前后端分离时代

  • 后端:后端控制层,服务层,数据访问层【后端团队】
  • 前端:前端控制层,视图层,【前端团队】
  • 伪造后端数据,json,已经存在数据,不需要后端,前端工程依旧可以跑起来
  • 前后端如何交互 ====》API
  • 前后端相对独立,松耦合
  • 前后端甚至可以部署在不同的服务器上

产生一个问题:

  • 前后端联调,前端和后端人员无法做到及时协商,解决问题,导致问题爆发
  • 需要一个东西可以解决这个问题

解决问题:

  • 首先指定计划,实时更新API,较低集成风险
  • 早些年:指定word计划文档
  • 前后端分离:
  • 前端测试后端接口:postman
  • 后端提供接口,需要使用更新最新的消息及改动!

官网:https://swagger.io/

Swagger

  • 号称世界上最流行的api框架
  • Restful Api文档在线自动生成工具==》api文档和api定义开发
  • 直接运行,可以在线测试api接口;
  • 执行多种语言(c#,java,php)

在项目中使用Swagger需要Springfox

  • swagger2
  • ui

SpringBoot集成Swagger

  1. 新建项目:SpringBoot-Swagger
  2. 导入相关依赖
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>3.0.0</version>
</dependency>
    <!-- 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>

新版(3.0)的直接加入启动器

  1. 创建一个helloword的项目
  2. 配置Swagger==>就可以启动看看效果了 3.0版本后不需要在加入@enableopenapi,和@enableswagger2这两个注解,
package com.hyc.springbootswagger.config;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
public class swaggerconfig {
}

路径:http://localhost:8080/swagger-ui/index.html

配置Swagger

配置呢,Swagger有自己的实例

我们使用docket来配置swagger的基本信息

@Bean
    public Docket docket(){
        return  new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo());
    }
    // 配置swagger基本信息
    private ApiInfo apiInfo(){
        Contact contact = new Contact("xxx", "hyc.com", "3132774018@qq.com");
        return new ApiInfo(
                "XXX的swagger",
                "签名",
                "1.0",
                "hyc.com",
                contact,
                "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList());
    }

应为没有set方法所以我们只能用构造器,貌似,还有一个什么biuder可以使用,有机会去试试

swagger配置扫描接口

select()来设置扫描

扫描接口配置的方法:

apis:

  • RequestHandlerSelectors扫描接口的方式
  • basePackage指定扫描包
  • any()扫描全部
  • none()不扫描
  • withclassannotation 扫描类的注解(里面必须放注解的反射对象)

path:过滤哪里什么路径

  • paths(PathSelectors.ant("/hyc/**"))
.select()
//指定我们需要基于什么包扫描
       .apis(RequestHandlerSelectors.basePackage("com.hyc.springbootswagger.controller"))
                .build();

使用了自定义,那么swagger就不会去扫描其他的位置,会扫描你指定的这个报下的请求

可以发现,现在只有controller下的请求才会被扫描

是否开启Swagger

.enable(false)//eanble决定了是否启动swagger

如果为false那我们就无法进入swagger-ui/index.html了

如何让我在测试的时候用swagger,发布的时候不用swagger

environment.acceptsProfiles来判断是否处在环境中

//配置swagger要使用的环境
        Profiles profiles = Profiles.of("dev", "test");

用profiles来配置使用环境

.enable(flag)//eanble判断是否启动swagger

api分组

分组,如何分组,

.groupName("胡宇辰")

分组,如何多个分组?,我有多个docket就可以有多个.groupName

@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("胡宇辰")
                .enable(flag)//eanble决定了是否启动swagger
                .select()
                //指定我们需要基于什么包扫描
                /*apis
                * RequestHandlerSelectors扫描接口的方式
                * basePackage指定扫描包
                * any()扫描全部
                * none()不扫描
                * withclassannotation 扫描类的注解(里面必须放注解的反射对象)
                *
                */
                .apis(RequestHandlerSelectors.basePackage("com.hyc.springbootswagger.controller"))
                /*path:过滤哪里什么路径
                *
                * */
//                .paths(PathSelectors.ant("/hyc/**"))
                .build();
    }
    @Bean
    public Docket docket1(Environment environment){
        return  new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .groupName("小刘");
    }
    @Bean
    public Docket docket2(Environment environment){
        return  new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .groupName("小郑");
    }

配置多个组

就是有很多个docket,

效果:

实体类

只要我们的接口中,有接口返回的是实体类,那么就是会被swagger扫描

我们写一个方法

@PostMapping("/user")
    public User user(){
        return new User();
    }

返回的是实体类user,user里有两个字段,name和age

页面效果图:

那我们看到的如@API这些注解是干什么的呢?

Swagger注解

用来解释类的用@Apimodel

@ApiModel("用户信息实体类")
public class User{  
}

用来解释类中的属性用@ApiModelProperty()

@ApiModelProperty("用户名字")
    public String name;
    @ApiModelProperty("用户年龄")
    public int age;

小疑问:我用private修饰的变量这么写就不显示,怎么办?

解决方案:写在get方法上就可以有效果了

Swagger测试接口

测试接口十分好用,

我们可以测试自己的接口是否有效

小测试:

测试接口:

@PostMapping("/userJY")
    public User user2(String name,int age){
        User user = new User(name,age);
        return user;
    }

测试页面步骤图

查看提交后的接口信息

Swagger总结

  1. Swagger最重大的使命就是使前后端人员之间的和谐关系有所好转
  2. 接口文档可以实时更新
  3. 可以在线测试后端接口,这个功能好评,爽的一批

Swagger是一个十分好用的工具,很多公司在使用

PS:处于安全考虑,我们在发布的时候需要关闭Swagger

功能

文件上传

配置:

# 上传文件总的最大值
spring.servlet.multipart.max-request-size=10MB
# 单个文件的最大值
spring.servlet.multipart.max-file-size=10MB
## jsp
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

单个文件上传的示例

@Controller
public class UploadController {
    private static final Logger LOGGER = LoggerFactory.getLogger(UploadController.class);
    @GetMapping("/upload")
    public String upload() {
        return "upload";
    }
    @PostMapping("/upload")
    @ResponseBody
    public String upload(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return "上传失败,请选择文件";
        }
        String fileName = file.getOriginalFilename();
        String filePath = "/Users/itinypocket/workspace/temp/";
        File dest = new File(filePath + fileName);
        try {
            file.transferTo(dest);
            LOGGER.info("上传成功");
            return "上传成功";
        } catch (IOException e) {
            LOGGER.error(e.toString(), e);
        }
        return "上传失败!";
    }
    
}

多个文件上传的示例

@GetMapping("/multiUpload")
public String multiUpload() {
    return "multiUpload";
}
@PostMapping("/multiUpload")
@ResponseBody
public String multiUpload(HttpServletRequest request) {
    List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file");
    String filePath = "/Users/itinypocket/workspace/temp/";
    for (int i = 0; i < files.size(); i++) {
        MultipartFile file = files.get(i);
        if (file.isEmpty()) {
            return "上传第" + (i++) + "个文件失败";
        }
        String fileName = file.getOriginalFilename();
        File dest = new File(filePath + fileName);
        try {
            file.transferTo(dest);
            LOGGER.info("第" + (i + 1) + "个文件上传成功");
        } catch (IOException e) {
            LOGGER.error(e.toString(), e);
            return "上传第" + (i++) + "个文件失败";
        }
    }
    return "上传成功";
}

任务

异步任务

小案例:我如何解决假如我访问了一个hello页面,页面调用的方法是睡眠3秒,再返回ok,那么再前端页面我就要等待空白页面3秒钟。如何解决?

Springboot中有一个注解叫@async异步任务

我们要使用他需要在主启动类开启注解支持@enableasync

代码示例

@Service
public class AsyncService {
        @Async
        public void hello(){
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("您好");
        }
}

这段代码会让执行方法的时候网页加载三秒。

控制层

@RestController
public class AsyncController {
    @Autowired
    AsyncService asyncService;
    @RequestMapping("/hello")
    public String hello(){
        asyncService.hello();
        return "ok";
    }
}

我们访问hello这个请求,就会等待三秒,之后页面返回ok,

执行顺序是:

发起请求-----》执行方法---》等三秒---》返回ok

我们启动了异步任务,并且将等待方法上加入注解@Aynsc

再次启动的时候,顺序就变成了这样 发起请求-----》执行方法---》等三秒(同时)---》等待完毕

---》返回ok(同时)

定时任务

gogogo函数接口

第一个接口:TaskExecutor // 任务执行者
第二个接口:TaskScheduler// 任务调度者
注解
@EnableScheduling//开启定时任务功能注解
@Scheduled

使用定时任务首先我们要在主启动类上添加注解开启定时任务:

@EnableScheduling//开启定时任务功能注解

之后就可以通过@Scheduled来设置cron表达式实现定时任务了

cron表达式

计划任务,是任务在约定的时间执行已经计划好的工作,这是表面的意思。在Linux中,我们经常用到 cron 服务器来完成这项工作。cron服务器可以根据配置文件约定的时间来执行特定的任务。

一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。
按顺序依次为

秒(0~59)
分钟(0~59)
小时(0~23)
天(月)(0~31,但是你需要考虑你月的天数)
月(0~11)
天(星期)(1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT)
年份(1970-2099)

字段 允许值 允许的特殊字符

秒 0-59 , - * /
分 0-59 , - * /
小时 0-23 , - * /
日期 1-31 , - * ? / L W C
月份 1-12 或者 JAN-DEC , - * /
星期 1-7 或者 SUN-SAT , - * ? / L C #
年(可选) 留空, 1970-2099 , - * /

PS:

  1. ?只能用在日期和星期,月上
  2. 在使用“L”参数时,不要指定列表或范围,因为这会导致问题

测试小例子:

@Service
public class ScheduledService {
    //需求:在一定的时间执行这个方法 方法千百种
    //cron表达式
    @Scheduled(cron = "0 14 10 * * ?")
    public void hello(){
        System.out.println("你被执行了");
    }
}

我想在每天的10点14分的时候,打印你被执行了,

邮件任务

首先要去qq邮箱开启服务

spring配置文件中的邮件配置

spring.mail.username=3132774018@qq.com
spring.mail.password=vymozuqhwxmadhae
spring.mail.host= smtp.qq.com
#开启加密验证
spring.mail.properties.mail.stmp.ssl.enable=true

spring中关于邮件的实现类:JavaMailSenderImpl

他是一个bean所以我们可以拿来使用

@Autowired
    JavaMailSenderImpl sender;

简单的邮件发送

@SpringBootTest
class Spring8TestApplicationTests {
    @Autowired
    JavaMailSenderImpl sender;
    @Test
    void contextLoads() {
        //一个简单的邮件的发送
        SimpleMailMessage message = new SimpleMailMessage();
        //标题
        message.setSubject("你好啊,hyc组内的成员,看到这条消息的时候 hyc还在为了大厂努力");
        //内容
        message.setText("冲进大厂没有什么是不可以的,好好努力,一切都在掌握之中");
        //发送给谁
        message.setTo("2549273958@qq.com");
        //谁来发送
        message.setFrom("3132774018@qq.com");
        sender.send(message);
    }
}

复杂邮件,带有附件,html,

我们这里使用sender.createMimeMessage的方式来创建复杂的邮件发送对象

springboot给我们提供了一个帮助类,MimeMessageHelper我们用这个helper对象来操作MImeMessage,

就可以完成复杂邮件发送了

@Test
    void contextLoads1() throws MessagingException {
        //复杂的邮件的发送
        MimeMessage mimeMessage = sender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
        helper.setSubject("hyc-plus");
        helper.setText("<p style='color:red'>你好</p>",true);
        //附件
        helper.addAttachment("1.jpg",new File("D:\\java工程师\\SpringBoot\\spring-8-test\\src\\main\\resources\\public\\1600837482167.jpg"));
        //发送给谁
        helper.setTo("3132774018@qq.com");
        //谁来发送
        helper.setFrom("3132774018@qq.com");
        sender.send(mimeMessage);
    }

邮件发送工具类

话不多说都在码里面了

MailsenderUtils:

@Component
public class MailsenderUtils {
    @Autowired
    private JavaMailSenderImpl mailSender;
    /**
     *
     * @param subject :邮件标题
     * @param text 邮件内容
     * @param html  是否开启html,
     * @param to     发送给谁
     * @param from    谁来发送
     * @param filename  附件名字
     * @param acc       附件路径
     * @return
     * 1 :发送成功
     * -1:发送失败
     */
    public  int MailsenderbyHyc(String subject, String text, boolean html, String to, String from,String filename, File acc){
        //复杂的邮件的发送
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        MimeMessageHelper helper = null;
        try {
            helper = new MimeMessageHelper(mimeMessage,true);
            helper.setSubject(subject);
            helper.setText(text,html);
            //附件
            helper.addAttachment(filename,acc);
            //发送给谁
            helper.setTo(to);
            //谁来发送
            helper.setFrom(from);
            mailSender.send(mimeMessage);
            return 1;
        } catch (MessagingException e) {
            e.printStackTrace();
            return -1;
        }
    }
}
目录
相关文章
|
14天前
|
安全 Java 开发者
详解SpringBoot的核心特性
SpringBoot是一个用于简化Spring应用程序开发的框架,它提供了一系列核心特性,使得开发者能够更快速、更简单地构建和部署Spring应用程序。本文将详细介绍SpringBoot的五个核心特性,并为每个特性提供三个子特性的详细解释。
20 1
|
2月前
|
安全 Java 数据库连接
SpringBoot 企业级简化开发(四)
SpringBoot 企业级简化开发
29 0
SpringBoot 企业级简化开发(四)
|
2月前
|
前端开发 Java 微服务
SpringBoot 企业级简化开发(一)
SpringBoot 企业级简化开发
108 1
|
2月前
|
前端开发 Java 数据库
SpringBoot 企业级简化开发(三)
SpringBoot 企业级简化开发
35 0
|
2月前
|
前端开发 JavaScript Java
SpringBoot 企业级简化开发(二)
SpringBoot 企业级简化开发
59 0
|
2月前
|
Java 应用服务中间件 Maven
简化springboot部署,太灵活方便了!
简化springboot部署,太灵活方便了!
10 0
|
2月前
|
存储 安全 Java
235基于SpringBoot的房屋交易平台的设计与实现
235基于SpringBoot的房屋交易平台的设计与实现
235基于SpringBoot的房屋交易平台的设计与实现
|
9月前
|
Java 数据库连接 Maven
从零玩转SpringBoot3-基础特性1
从零玩转SpringBoot3-基础特性
199 0
|
SQL Java 数据库
如何利用SpringBoot 搭建微服务?
这篇就利用SpringBoot 搭建微服务,带大家从代码的角度来加深对微服务的概念,理解了概念才会知道微服务怎么架构的,组件与组件之间是如何互通通信的
466 1
如何利用SpringBoot 搭建微服务?
|
Java Maven Spring
SpringBoot多环境适配之道
本文是应用配置中心的第三篇,第一篇介绍了配置演化之路,第二篇介绍了在传统项目中以Maven作为多环境支持的方式。这篇将以SpringBoot为例,重点阐述在SpringBoot中如何适配多环境。
136 0
SpringBoot多环境适配之道