springboot-8-企业开发
一、邮件发送
流程:
mbqplwpheeyvgdjh
首先需要开启POS3/SMTP服务,这是一个邮件传输协议
点击开启
导入依赖
<!--mail-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
参数配置
# 配置邮件发送服务器得地址和端口(465或者587)
spring.mail.host=smtp.qq.com
spring.mail.port=587
# 配置用户账号和密码
spring.mail.username=1847193435@qq.com
spring.mail.password=mbqplwpheeyvgdjh
# 配置默认编码方式、SSL连接配置、最后开启debug可以查看文件日志
spring.mail.default-encoding=UTF-8
spring.mail.properties.mail.smtp.socketFactory.class = javax.net.ssl.SSLSocketFactor
spring.mail.properties.mail.debug = true
配置邮件发送组件
@Component
public class MailService {
@Autowired
JavaMailSender javaMailSender;
//有抄送人
public void sendMailWitrhCc(String from,
String to,
String cc,
String subject,
String content){
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setFrom(from);
simpleMailMessage.setTo(to);
simpleMailMessage.setCc(cc);
simpleMailMessage.setSubject(subject);
simpleMailMessage.setText(content);
javaMailSender.send(simpleMailMessage);
}
//无抄送人
public void sendMail(String from,
String to,
String subject,
String content){
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setFrom(from);
simpleMailMessage.setTo(to);
simpleMailMessage.setSubject(subject);
simpleMailMessage.setText(content);
javaMailSender.send(simpleMailMessage);
}
}
测试发送
@SpringBootTest
class EmailApplicationTests {
@Autowired
MailService mailService;
@Test
void contextLoads() {
mailService.sendMail("1847193435@qq.com",
"1847193435@qq.com",
"test",
"测试邮件");
}
}
发送带附件邮件:
public void sendAttachFileMail(String from,
String to,
String subject,
String content,
File file) {
try{
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
//MimeMessageHelper简化了邮件配置,第二个参数true表示构造一个multipart message类型得邮件
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content);
helper.addAttachment(file.getName(),file);
javaMailSender.send(mimeMessage);
}catch (MessagingException e){
e.printStackTrace();
}
}
测试
@SpringBootTest
class EmailApplicationTests {
@Autowired
MailService mailService;
@Test
void contextLoads() {
mailService.sendAttachFileMail("1847193435@qq.com",
"1847193435@qq.com",
"test",
"文件测试附带",
new File("C:\\Users\\86186\\Desktop\\xml语法.md"));
}
}
发送带图片资源的邮件:
public void sendMailWithImg(String from,
String to,
String subject,
String content,
String[] srcPaths,
String[] resIds){
if (srcPaths.length != resIds.length){
System.out.println("发送错误");
return;
}
try{
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
//后面这个true参数表示html格式
helper.setText(content,true);
for (int i = 0 ; i<srcPaths.length;i++){
FileSystemResource res = new FileSystemResource(new File(srcPaths[i]));
helper.addInline(resIds[i],res);
}
javaMailSender.send(message);
}catch (MessagingException e){
System.out.println("发送错误");
}
}
测试
@Test
void contextLoads() {
mailService.sendMailWithImg("1847193435@qq.com",
"1247166001@qq.com",
"springboot基于java测试",
"<div><h1>test发送邮件</h1>" +
" 正常的lwy:<div><img style='width: 100px;height: 100px;' src='cid:p1'></div>\n" +
" 猖狂的lwy:<div><img style='width: 100px;height: 100px;' src='cid:p2'></div>\n" +
"</div>",
new String[]{"C:\\Users\\86186\\Pictures\\lwy\\1.jpg","C:\\Users\\86186\\Pictures\\lwy\\2.jpg"},
new String[]{"p1","p2"}
);
}
使用thymeleaf构建邮件模板
对于格式复杂的邮件,如果采用字符串进行HTML模板拼接,不但容易出错,而且不易维护,使用html模板就可以很好的解决这个问题
其实最终的目的还是去把我们要加载的信息和模板结合然后再作为邮件的content发送出去
流程:
导入依赖
<!--mail-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
创建模板
<!DOCTYPE html>
<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>
<head>
<title>邮件</title>
</head>
<body>
<h1>邮箱激活</h1>
<h4>你的注册信息如下是:</h4>
<div>
<table border="1">
<tr>
<th>用户名</th>
<th th:text="${username}"></th>
</tr>
<tr>
<th>性别</th>
<th th:text="${gender}"></th>
</tr>
</table>
</div>
<div><a th:href="@{https://www.baidu.com/}">核对无误请点击本链接来激活邮箱</a> </div>
</body>
</html>
MailService中添加方法
//发送html邮件
public void sendHtmlMail(String from,
String to,
String subject,
String content){
try{
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content,true);
javaMailSender.send(message);
}catch (MessagingException e){
System.out.println("发送错误");
}
}
测试
@Test
void contextLoads() {
//注意这个context是thymeleaf中的
Context context = new Context();
context.setVariable("username","sang");
context.setVariable("gender","男");
String content = templateEngine.process("mailtemplate.html", context);
mailService.sendHtmlMail("1847193435@qq.com",
"1847193435@qq.com",
"testtemplate",
content);
}
二、定时任务
简单的定时任务用@schedule就可以完成,
复杂的定时任务需要整合Quartz来实现
流程:
依赖只需要是web依赖即可
在项目启动类上添加一个@EnableScheduling注解,来开启定时任务
@SpringBootApplication
@EnableScheduling
public class ScheduleApplication {
public static void main(String[] args) {
SpringApplication.run(ScheduleApplication.class, args);
}
}
配置定时任务
@Component
public class MySchedule {
@Scheduled(fixedDelay = 1000)
public void fixedDelay(){
System.out.println("fixedDelay:"+new Date());
}
@Scheduled(fixedRate = 2000)
public void fixedRate(){
System.out.println("fixedRate:"+new Date());
}
@Scheduled(initialDelay = 1000,fixedRate = 2000)
public void initialDelay(){
System.out.println("initialDelay:"+new Date());
}
@Scheduled(cron = "0 * * * * ?")
public void cron(){
System.out.println("cron: "+new Date());
}
}
整合Quartz:
主要思想就是:需要通过组件向IOC容器提供三个bean,JobDetail,Trigger,SchedulerFactory
JobDetail --> Trigger --> SchedulerFactory
流程:
导入依赖:
<!--quartz-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
编写定时任务
- 一种是直接放入到IOC容器中的组件
- 无需继承其他类
- 不能传输参数
- 一种是需要加入参数的类似于pojo的类
- 需要继承QuartzJobBean,并重写executeInternal方法
- 主要用来进行需要参数的定时任务
@Component
public class MyFirstJob {
public void sayHello(){
System.out.println("MyFirstJob: "+new Date());
}
}
//这个后来需要实例化才用,所以不需要放到IOC容器中去
public class MySecondJob extends QuartzJobBean {
String name;
public MySecondJob() {
}
public void setName(String name) {
this.name = name;
}
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
System.out.println("hello "+name+new Date());
}
}
开始配置JobDetail,分别对应两个Job
//对应没有继承QuartzJobBean的那个IOC容器中的bean
@Bean
MethodInvokingJobDetailFactoryBean jobDetail1(){
MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();
bean.setTargetBeanName("myFirstJob");
bean.setTargetMethod("sayHello");
return bean;
}
@Bean
JobDetailFactoryBean jobDetail2(){
//创建一个工厂bean
JobDetailFactoryBean bean = new JobDetailFactoryBean();
//把要加载的定时任务类加载到IOC容器中去,但这个时候类中的参数还是空的
bean.setJobClass(MySecondJob.class);
//把我们需要的参数放在这个map集合里面
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("name","sang");
//把参数加载到这个工厂bean中来
bean.setJobDataMap(jobDataMap);
bean.setDurability(true);
return bean;
}
开始配置Trigger(触发器),有两种触发器
@Bean
SimpleTriggerFactoryBean simpleTriggerFactoryBean(){
SimpleTriggerFactoryBean bean = new SimpleTriggerFactoryBean();
bean.setJobDetail(jobDetail1().getObject());
bean.setRepeatCount(3);
bean.setStartDelay(1000);
bean.setRepeatInterval(2000);
return bean;
}
@Bean
CronTriggerFactoryBean cronTriggerFactoryBean(){
CronTriggerFactoryBean bean = new CronTriggerFactoryBean();
bean.setJobDetail(jobDetail2().getObject());
bean.setCronExpression("* * * * * ?");
return bean;
}
最后把触发器又配置到定时工厂的bean里面
@Bean
SchedulerFactoryBean schedulerFactoryBean(){
SchedulerFactoryBean bean = new SchedulerFactoryBean();
SimpleTrigger simpleTrigger = simpleTriggerFactoryBean().getObject();
CronTrigger cronTrigger = cronTriggerFactoryBean().getObject();
bean.setTriggers(simpleTrigger,cronTrigger);
return bean;
}
三、批处理
spring batch框架:
提供了记录/跟踪、事务管理、作业处理统计、作业重启以及资源管理等功能。
主要提供ItemReader、ItemProccessor、ItemWriter来完成数据的读取、处理以及写出操作,并且可以将批处理的执行状态持久化到数据库中。
流程:
略
四、swagger2
简介:
帮助软件开发人员设计,构建,记录和使用RESTful Web服务,他将代码和文档融为一体,可以完美解决上面的问题,使开发人员将大部分精力集中到业务中去
流程:
导入依赖:
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!--swagger-ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
swagger配置
需要添加@EnableSwagger2开启配置
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
Docket docket(){
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.wang.control"))
.paths(PathSelectors.any())
.build()
.apiInfo(
new ApiInfoBuilder().description("为人师开发文档")
.contact(
new Contact("江南一点南","https://www.cnblogs.com/CoderWangEx/","1847193435@qq.com")
).version("v1.0")
.title("API测试文档")
.license("Apache2.0")
.licenseUrl("http://www.apache.org/license/LICENSE-2.0")
.build()
);
}
}
pojo类
@Data
@ApiModel(value = "用户实体类",description = "用户信息描述类")
public class User {
@ApiModelProperty(value = "用户名")
private String username;
@ApiModelProperty(value = "用户地址")
private String address;
}
控制器(restful风格)
@RestController
@Api(tags = "用户数据接口")
public class UserControl {
//需要添加两个信息,一个是方法简介,一个是传入参数简介
@ApiOperation(value = "查询用户",notes = "根据id查询用户")
//paramType是指方法参数的类型,可选值有path(参数获取方式@PathVariable)、query(参数获取方式@RequestParam)、header(参数获取方式@RequestHeader)、body以及form
@ApiImplicitParam(paramType = "path",name = "id",value = "用户id",required = true)
@GetMapping("/users/{id}")
public String getUserById(@PathVariable("id")Integer id){
return "/user/"+id;
}
@ApiResponses({
@ApiResponse(code = 200,message = "删除成功!"),
@ApiResponse(code = 500,message = "删除失败!")
})
@ApiOperation(value = "删除用户",notes = "通过id删除用户")
@ApiImplicitParam(paramType = "path",name = "id",value = "用户id",required = true)
@DeleteMapping("/user/{id}")
public String deleteUserById(@PathVariable()Integer id){
return id+"已被删除";
}
@ApiOperation(value = "添加用户",notes = "添加一个用户,传入用户名和地址")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "query",name = "username",value = "用户名",required = true,defaultValue = "sang"),
@ApiImplicitParam(paramType = "query",name = "address",value = "地址",required = true,defaultValue = "北京")
})
@PostMapping("/user")
public String addUser(@RequestParam(value = "username")String username,
@RequestParam(value = "address")String address){
return username+":"+address;
}
@ApiOperation(value = "修改用户",notes = "通过id,去修改用户的地址")
@ApiImplicitParam(paramType = "body",name = "user",value = "用户对象",required = true)
@PutMapping("/user")
public String updateUser(@RequestBody() User user){
return user.toString();
}
@ApiIgnore
@GetMapping("/ignore")
public String ignoreMethod(){
return "已被忽略";
}
}
五、数据校验
流程:
导入依赖:
<!--jsr303-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
出错信息参数配置
通过LocalValidationFactoryBean的源码可以知道默认的ValidationMessageSource(校验出错时的提示文件)是resource目录下的ValidationMessages.properties文件
故我们需要在resource目录下创建一个ValidationMessages.properties文件,用于放置错误信息
user.name.size=用户名长度介于5到10格字符
user.address.notnull=用户地址不能为空
user.age.size=年龄输入不正确
user.email.notnull=邮箱不能为空
user.email.pattern=邮箱格式不正确
pojo类
@Data
public class User {
private Integer id;
@Size(min = 5,max = 10,message = "{user.name.size}")
private String name;
@NotNull
private String address;
@DecimalMin(value = "1",message = "{user.age.size}")
@DecimalMax(value = "100",message = "{user.age.size}")
private Integer age;
@Email(message = "{user.email.pattern}")
@NotNull(message = "{user.email.notnull}")
private String email;
}
控制器:
在需要校验的参数前加上注解@Validation,后面再加上BindingResult result用于接收错误信息
@RestController
public class UserControl {
@PostMapping("/user")
public List<String> addUser(@Validated User user, BindingResult result){
ArrayList<String> errors = new ArrayList<>();
if (result.hasErrors()){
List<ObjectError> allErrors = result.getAllErrors();
for (ObjectError error : allErrors){
errors.add(error.getDefaultMessage());
}
}
return errors;
}
}
没有找到配置出错信息的文件:
应该是文件名错了
ValidationMessages.properties
注意message后有个s
报错信息乱码:
需要再idea中改一下ValidationMessages.properties的编码格式
修改ValidationMessages.properties的编码格式,改成UTF-8。
File > Settings > Editor > File Encodings,
添加ValidationMessages.properties,指定编码为UTF-8,并勾选Transparent native-to-ascii conversion,
再apply ,ok。
如果还不行,就把这个文件删掉,再创建就可以了
分组校验:
流程:
导入依赖,
配置ValidationMessages.properties
创建两个分组接口
public interface ValidationGroup1 {
}
public interface ValidationGroup2 {
}
然后在配置pojo的时候注解的参数加上group,即可分组
public class Employee {
private Integer id;
@Size(min = 5,max = 10,message = "{user.name.size}",groups = ValidationGroup1.class)
private String name;
@NotNull(message = "{user.address.notnull}",groups = ValidationGroup2.class)
private String address;
@DecimalMin(value = "1",message = "{user.age.size}")
@DecimalMax(value = "200",message = "{user.age.size}")
private Integer age;
@Email(message = "{user.email.pattern}")
@NotNull(message = "{user.email.notnull}")
private String email;
}
控制器,在注解@Validated的参数表示出要用哪个分组
//这里表示使用第二种分配方式
@PostMapping("/user2")
public List<String> addUser2(@Validated(value = ValidationGroup2.class) User user, BindingResult result){
ArrayList<String> errors = new ArrayList<>();
if (result.hasErrors()){
List<ObjectError> allErrors = result.getAllErrors();
for (ObjectError error : allErrors){
errors.add(error.getDefaultMessage());
}
}
return errors;
}
常用校验注解
废话不多说,直接上表格说明:
注解 | 作用类型 | 解释 |
---|---|---|
@NotNull | 任何类型 | 属性不能为null |
@NotEmpty | 集合 | 集合不能为null,且size大于0 |
@NotBlanck | 字符串、字符 | 字符类不能为null,且去掉空格之后长度大于0 |
@AssertTrue | Boolean、boolean | 布尔属性必须是true |
@Min | 数字类型(原子和包装) | 限定数字的最小值(整型) |
@Max | 同@Min | 限定数字的最大值(整型) |
@DecimalMin | 同@Min | 限定数字的最小值(字符串,可以是小数) |
@DecimalMax | 同@Min | 限定数字的最大值(字符串,可以是小数) |
@Range | 数字类型(原子和包装) | 限定数字范围(长整型) |
@Length | 字符串 | 限定字符串长度 |
@Size | 集合 | 限定集合大小 |
@Past | 时间、日期 | 必须是一个过去的时间或日期 |
@Future | 时期、时间 | 必须是一个未来的时间或日期 |
字符串 | 必须是一个邮箱格式 | |
@Pattern | 字符串、字符 | 正则匹配字符串 |
springboot-8-企业开发的更多相关文章
- 企业开发中选择logback而不是log4j的理由
不知道看到这篇文章的Java工程师有没有考虑过这个问题:为什么在企业开发中会选择logback来记录日志,而不是log4j呢? 如果你以前没有考虑过这个问题,那么现在如果让你考虑一下,你可能觉的会是因 ...
- Silverlight分享一套企业开发主题
Silverlight分享一套企业开发主题 Silverlight默认主题时间长了,也视觉疲劳了,于是上网上找了下Silverlight主题.发现SL的主题并不多,下面这套JetPack主题还是SL4 ...
- ASP.NET MVC企业开发的基本环境
ASP.NET MVC企业开发的基本环境[资源服务器概念] 学完了ASP.NET MVC4 IN ACTION 六波以后 企业开发演习 标签:AaronYang 茗洋 EasyUI1.3.4 ...
- SpringBoot学习(七)-->SpringBoot在web开发中的配置
SpringBoot在web开发中的配置 Web开发的自动配置类:在Maven Dependencies-->spring-boot-1.5.2.RELEASE.jar-->org.spr ...
- 在“非软件企业”开发软件的困局 ZT
软件产品广泛服务于各行业,其开发具有高科技.高投入.高产出.高风险的特点.在项目开发和软件应用中,只有将人员能力的发挥与科学技术的使用应用市场的认识进行最佳的融合,才能发挥软件的效益.普通企业虽涉足软 ...
- springboot多模块开发以及整合dubbo\zookeeper进行服务管理
之前研究了springboot单工程的使用,参考git地址:https://github.com/qiao-zhi/springboot-ssm 下面研究springboot多模块开发的过程. 1.模 ...
- 【AaronYang第一讲】ASP.NET MVC企业开发的基本环境[资源服务器概念]
学完了ASP.NET MVC4 IN ACTION 六波以后 企业开发演习 标签:AaronYang 茗洋 EasyUI1.3.4 ASP.NET MVC 3 本篇博客地址:http://ww ...
- 大数据技术之_09_Flume学习_Flume概述+Flume快速入门+Flume企业开发案例+Flume监控之Ganglia+Flume高级之自定义MySQLSource+Flume企业真实面试题(重点)
第1章 Flume概述1.1 Flume定义1.2 Flume组成架构1.2.1 Agent1.2.2 Source1.2.3 Channel1.2.4 Sink1.2.5 Event1.3 Flum ...
- SpringBoot:Web开发
西部开源-秦疆老师:基于SpringBoot 2.1.6 的博客教程 , 基于atguigu 1.5.x 视频优化 秦老师交流Q群号: 664386224 未授权禁止转载!编辑不易 , 转发请注明出处 ...
- 吴裕雄--天生自然PythonDjangoWeb企业开发:需求
开发或者做一个项目,是要有一个需求过来的,而不是无缘无故的,启动一个项目,或者推动整个项目进行下一步迭代.这个需求可能是根据用户反馈增加的,可能是老板提出来的,也有可能是产品经理提出来的,但是无论是什 ...
随机推荐
- SQL进阶总结(一)
学而不思则罔,趁着假期好好总结下SQL的编程知识. 掌握SQL,首先有两个知识点要明确,要贯穿在我们整个学习SQL的过程中. SQL 不同于之前学习的面向过程.面向编程语言,SQL是一门面向集合的编程 ...
- postman 获取Json 返回值的某个键值并进行断言判定
前提: 当前接口返回的结果值为json格式 1.将响应正文信息copy 到 https://www.bejson.com/ 便于查看 2.取值并进行断言编写 //json对象解析取值 var jd ...
- jsp中basa标签的使用
<base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${page ...
- canal+mysql+kafka实时数据同步安装、配置
canal+mysql+kafka安装配置 概述 简介 canal译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费. 基于日志增量订阅和消费的业务包括 数 ...
- 你有一份经典SQL语句大全,请注意查收
一.基础部分 1.创建数据库 CREATE DATABASE dbname 2.删除数据库 DROP DATABASE dbname 3.创建新表 CREATE TABLE tabname(col1 ...
- 《手把手教你》系列基础篇之(一)-java+ selenium自动化测试-环境搭建(上)(详细教程)
1.简介 jmeter系列的文章结束,本来想趁热打铁顺别将Jmeter和接口测试介绍一下,但是感觉Jmeter时间太长了怕大家吃腻了,还有一个原因就是许多小伙伴们或者童鞋们私信问宏哥什么时候可以有ja ...
- UGUI ScrollRect 鼠标滑动灵敏度调节
- 乘风破浪,Windows11设计和开发指导,全新图标字体和云母材质
Windows11全新的布局设计 Windows 11全新的布局设计已设计为支持现代应用体验.渐进的圆角.嵌套元素和一致的排水沟相结合,营造出柔和.平静.平易近人的效果,强调目的的统一和易用性. ht ...
- Custom Controller CollectionQT样式自定义 001 :SliderLineEdit 滑动输入框
主要是继承QLineEdit类重新实现其鼠标事件,建议禁用输入框默认的菜单项. SliderLineEdit 滑动输入框 参照图形平台 Adobe系列中属性输入框 做的样式,支持点击编辑和长按鼠标拖动 ...
- xf浅谈_最短路
最短路问题(short-path problem):最短路问题是图论研究中的一个经典算法问题,指在寻找图(由结点和路径组成的)中两结点之间的最短路径.算法具体的形式包括: 1.确定起点的最短路径问题 ...