diff --git a/READ.md b/READ.md index 83ac6dd8f5557e8ef004186e788f8959ea0b3f5a..05b296f163b07026dab7ca1d7bb63f00ac56d6b7 100644 --- a/READ.md +++ b/READ.md @@ -27,6 +27,12 @@ - web模块 - 发邮件 + +- 数据校验规则 + +- 乱码问题 WebMvcConfigurationSupport + +- 批处理 ## 三.链接 diff --git a/pom.xml b/pom.xml index 508ff1fd118fcb0a2ee8ed929e62f2ca612a49e4..f9293f909a97dc7d95dbbddddc99e0679db65bde 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,9 @@ Demo project for Spring Boot 1.8 + + UTF-8 + UTF-8 @@ -113,6 +116,14 @@ org.springframework.boot spring-boot-starter-mail + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-batch + diff --git a/src/main/java/com/kwan/springbootkwan/SpringBootKwanApplication.java b/src/main/java/com/kwan/springbootkwan/SpringBootKwanApplication.java index d2a159195f0db6977ccd1f1096c7df8deea5707e..cc603b3be2e283bcabbbb228cb0a7494e9207a3d 100644 --- a/src/main/java/com/kwan/springbootkwan/SpringBootKwanApplication.java +++ b/src/main/java/com/kwan/springbootkwan/SpringBootKwanApplication.java @@ -1,4 +1,5 @@ package com.kwan.springbootkwan; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -6,6 +7,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; @EnableScheduling @SpringBootApplication +@EnableBatchProcessing public class SpringBootKwanApplication { public static void main(String[] args) { diff --git a/src/main/java/com/kwan/springbootkwan/config/CsvBatchJobConfig.java b/src/main/java/com/kwan/springbootkwan/config/CsvBatchJobConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..96a55253a468c580264c37dc9cc187adf48a1eca --- /dev/null +++ b/src/main/java/com/kwan/springbootkwan/config/CsvBatchJobConfig.java @@ -0,0 +1,83 @@ +package com.kwan.springbootkwan.config; + +import com.kwan.springbootkwan.entity.Person; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; +import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider; +import org.springframework.batch.item.database.JdbcBatchItemWriter; +import org.springframework.batch.item.file.FlatFileItemReader; +import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; +import org.springframework.batch.item.file.mapping.DefaultLineMapper; +import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; + +import javax.sql.DataSource; + +@Configuration +public class CsvBatchJobConfig { + + + @Autowired + JobBuilderFactory jobBuilderFactory; + @Autowired + StepBuilderFactory stepBuilderFactory; + @Autowired + DataSource dataSource; + + + @Bean + @StepScope + FlatFileItemReader itemReader() { + FlatFileItemReader reader = new FlatFileItemReader<>(); + reader.setLinesToSkip(1); + reader.setResource(new ClassPathResource("data.csv")); + reader.setLineMapper(new DefaultLineMapper() {{ + setLineTokenizer(new DelimitedLineTokenizer() { + { + setNames("id", "username", "address", "gender"); + //配置列与列之间的间隔符(将通过间隔符对每一行的数据进行切分),最后设置要映射的实体类属性即可 + setDelimiter(","); + } + }); + setFieldSetMapper(new BeanWrapperFieldSetMapper() { + { + setTargetType(Person.class); + } + }); + + }}); + return reader; + } + + @Bean + public JdbcBatchItemWriter jdbcBatchItemWriter() { + JdbcBatchItemWriter writer = new JdbcBatchItemWriter(); + writer.setDataSource(dataSource); + writer.setSql("insert into person(id, username,address,gender)" + "values (:id, :username, :address, :gender)"); + writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>()); + return writer; + } + + @Bean + Step csvStep() { + return stepBuilderFactory.get("csvStep") + .chunk(2) + .reader(itemReader()) + .writer(jdbcBatchItemWriter()) + .build(); + } + + @Bean + Job csvJob() { + return jobBuilderFactory.get("csvJob") + .start(csvStep()) + .build(); + + } +} diff --git a/src/main/java/com/kwan/springbootkwan/config/MyWebMvcConfig.java b/src/main/java/com/kwan/springbootkwan/config/MyWebMvcConfig.java index fcab5b2570b6643d56855d58dba528dec6860d1f..42bc12caf43f79490a552242974dc271054bee20 100644 --- a/src/main/java/com/kwan/springbootkwan/config/MyWebMvcConfig.java +++ b/src/main/java/com/kwan/springbootkwan/config/MyWebMvcConfig.java @@ -1,10 +1,23 @@ package com.kwan.springbootkwan.config; +import org.springframework.boot.validation.MessageInterpolatorFactory; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.CorsRegistry; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.context.support.ResourceBundleMessageSource; +import org.springframework.format.FormatterRegistry; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.validation.MessageCodesResolver; +import org.springframework.validation.Validator; +import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.HandlerMethodReturnValueHandler; +import org.springframework.web.servlet.HandlerExceptionResolver; +import org.springframework.web.servlet.config.annotation.*; + +import java.nio.charset.StandardCharsets; +import java.util.List; /** * 全局webconfig-跨域配置 @@ -14,7 +27,49 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; * @date : 2022/12/19 16:11 */ @Configuration -public class MyWebMvcConfig implements WebMvcConfigurer { +public class MyWebMvcConfig extends WebMvcConfigurationSupport implements WebMvcConfigurer { + + @Override + public void extendMessageConverters(List> converters) { + // 解决controller返回字符串中文乱码问题 + for (HttpMessageConverter converter : converters) { + if (converter instanceof StringHttpMessageConverter) { + ((StringHttpMessageConverter) converter).setDefaultCharset(StandardCharsets.UTF_8); + } else if (converter instanceof MappingJackson2HttpMessageConverter) { + ((MappingJackson2HttpMessageConverter) converter).setDefaultCharset(StandardCharsets.UTF_8); + } + } + } + + @Override + public void configureHandlerExceptionResolvers(List resolvers) { + WebMvcConfigurer.super.configureHandlerExceptionResolvers(resolvers); + } + + @Override + public void extendHandlerExceptionResolvers(List resolvers) { + WebMvcConfigurer.super.extendHandlerExceptionResolvers(resolvers); + } + + @Override + public Validator getValidator() { + ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); + messageSource.setDefaultEncoding("utf-8");// 读取配置文件的编码格式 + messageSource.setCacheMillis(-1);// 缓存时间,-1表示不过期 + messageSource.setBasename("ValidationMessages");// 配置文件前缀名,设置为Messages,那你的配置文件必须以Messages.properties/Message_en.properties... + + LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean(); + MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory(); + factoryBean.setMessageInterpolator(interpolatorFactory.getObject()); + factoryBean.setValidationMessageSource(messageSource); + return factoryBean; + } + + @Override + public MessageCodesResolver getMessageCodesResolver() { + return WebMvcConfigurer.super.getMessageCodesResolver(); + } + /** * 配置静态资源 * @@ -26,6 +81,31 @@ public class MyWebMvcConfig implements WebMvcConfigurer { .addResourceLocations("classpath:/static/"); } + @Override + public void configurePathMatch(PathMatchConfigurer configurer) { + WebMvcConfigurer.super.configurePathMatch(configurer); + } + + @Override + public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { + WebMvcConfigurer.super.configureContentNegotiation(configurer); + } + + @Override + public void configureAsyncSupport(AsyncSupportConfigurer configurer) { + WebMvcConfigurer.super.configureAsyncSupport(configurer); + } + + @Override + public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { + WebMvcConfigurer.super.configureDefaultServletHandling(configurer); + } + + @Override + public void addFormatters(FormatterRegistry registry) { + WebMvcConfigurer.super.addFormatters(registry); + } + /** * 配置拦截器 * @@ -51,4 +131,29 @@ public class MyWebMvcConfig implements WebMvcConfigurer { .maxAge(1800) .allowedOrigins("http://localhost:8081"); } + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + WebMvcConfigurer.super.addViewControllers(registry); + } + + @Override + public void configureViewResolvers(ViewResolverRegistry registry) { + WebMvcConfigurer.super.configureViewResolvers(registry); + } + + @Override + public void addArgumentResolvers(List resolvers) { + WebMvcConfigurer.super.addArgumentResolvers(resolvers); + } + + @Override + public void addReturnValueHandlers(List handlers) { + WebMvcConfigurer.super.addReturnValueHandlers(handlers); + } + + @Override + public void configureMessageConverters(List> converters) { + WebMvcConfigurer.super.configureMessageConverters(converters); + } } diff --git a/src/main/java/com/kwan/springbootkwan/controller/PersonController.java b/src/main/java/com/kwan/springbootkwan/controller/PersonController.java index 92ee4b74c96f04637c709c85e55a8a3202831832..47a38c3135a0d53a6be8b9f458f59a04284534c9 100644 --- a/src/main/java/com/kwan/springbootkwan/controller/PersonController.java +++ b/src/main/java/com/kwan/springbootkwan/controller/PersonController.java @@ -5,6 +5,9 @@ import com.kwan.springbootkwan.entity.User; import com.kwan.springbootkwan.service.IUserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.launch.JobLauncher; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -22,6 +25,12 @@ import java.util.List; @RestController @RequestMapping("/person") public class PersonController { + + @Autowired + private JobLauncher jobLauncher; + @Autowired + private Job job; + /** * { * "name": "zhang san", @@ -33,9 +42,18 @@ public class PersonController { @GetMapping("/person") public Person person() { Person person = new Person(); - person.setName("zhang san"); - person.setAge(24); - person.setBirthday(new Date()); + person.setUsername("zhang san"); + person.setId(24); + person.setAddress("湖北"); return person; } + + @GetMapping("/hello") + public void hello() { + try { + jobLauncher.run(job, new JobParameters()); + } catch (Exception e) { + e.printStackTrace(); + } + } } \ No newline at end of file diff --git a/src/main/java/com/kwan/springbootkwan/controller/UserController.java b/src/main/java/com/kwan/springbootkwan/controller/UserController.java index 65e944e1a74693b027a6415be563d16aff6d0c0d..158bb87917bf23b2871818a1b4e4624a35c2d00d 100644 --- a/src/main/java/com/kwan/springbootkwan/controller/UserController.java +++ b/src/main/java/com/kwan/springbootkwan/controller/UserController.java @@ -1,13 +1,21 @@ package com.kwan.springbootkwan.controller; +import com.kwan.springbootkwan.entity.Student; import com.kwan.springbootkwan.entity.User; import com.kwan.springbootkwan.service.IUserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpRequest; +import org.springframework.validation.BindingResult; +import org.springframework.validation.ObjectError; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; import java.util.List; /** @@ -38,4 +46,18 @@ public class UserController { public User getUserById(@PathVariable Integer id) { return userService.getUserById(id); } + + + @PostMapping(value = "/student",produces = "application/json;charset=utf-8") + public List addUser(@RequestBody @Validated Student student, BindingResult result ) throws UnsupportedEncodingException { + List errors = new ArrayList<>(); + if (result.hasErrors()) { + List allErrors = result.getAllErrors(); + for (ObjectError error : allErrors) { + errors.add(error.getDefaultMessage()); + } + } + log.info("errors={}", errors); + return errors; + } } \ No newline at end of file diff --git a/src/main/java/com/kwan/springbootkwan/entity/MailInfo.java b/src/main/java/com/kwan/springbootkwan/entity/MailInfo.java index c9d88628a51b9ff9ee1e84cf176f55c283eda51e..ec6b71d9a4c6793cab0db732eb4aefa14e59c141 100644 --- a/src/main/java/com/kwan/springbootkwan/entity/MailInfo.java +++ b/src/main/java/com/kwan/springbootkwan/entity/MailInfo.java @@ -1,5 +1,6 @@ package com.kwan.springbootkwan.entity; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.Map; @@ -13,16 +14,16 @@ import java.util.Map; */ @Data public class MailInfo { - // 邮件接收人 + @ApiModelProperty(value = "邮件接收人") private String[] receiver; - // 邮件主题 + @ApiModelProperty(value = "邮件主题") private String subject; - // 邮件的文本内容 + @ApiModelProperty(value = "邮件的文本内容") private String content; - // 抄送人 + @ApiModelProperty(value = "抄送人") private String[] cc; - // 邮件附件的文件名 + @ApiModelProperty(value = "邮件附件的文件名") private String[] attachFileNames; - // 邮件内容内嵌图片 + @ApiModelProperty(value = "邮件内容内嵌图片") private Map imageMap; } diff --git a/src/main/java/com/kwan/springbootkwan/entity/Person.java b/src/main/java/com/kwan/springbootkwan/entity/Person.java index a609748fff6ba33bf73a3eec7522bafd7a895826..93db08fe81f79b3a21d3225974acc6b53acedc23 100644 --- a/src/main/java/com/kwan/springbootkwan/entity/Person.java +++ b/src/main/java/com/kwan/springbootkwan/entity/Person.java @@ -1,42 +1,20 @@ package com.kwan.springbootkwan.entity; -import com.fasterxml.jackson.annotation.JsonFormat; +import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; +import lombok.Data; -import java.util.Date; - +@Data +@TableName(value = "person") @ApiModel(value = "用户基本信息") public class Person { - @ApiModelProperty(value = "姓名") - private String name; - @ApiModelProperty(value = "年龄") - private Integer age; - @ApiModelProperty(value = "生日") - @JsonFormat(pattern = "yyyy-MM-dd") - private Date birthday; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getAge() { - return age; - } - - public void setAge(Integer age) { - this.age = age; - } - - public Date getBirthday() { - return birthday; - } - - public void setBirthday(Date birthday) { - this.birthday = birthday; - } -} + @ApiModelProperty(value = "主键") + private Integer id; + @ApiModelProperty(value = "名称") + private String username; + @ApiModelProperty(value = "地址") + private String address; + @ApiModelProperty(value = "性别") + private String gender; +} \ No newline at end of file diff --git a/src/main/java/com/kwan/springbootkwan/entity/Student.java b/src/main/java/com/kwan/springbootkwan/entity/Student.java new file mode 100644 index 0000000000000000000000000000000000000000..ec4408ea7b304db0d0c3f25255e50b06578831b1 --- /dev/null +++ b/src/main/java/com/kwan/springbootkwan/entity/Student.java @@ -0,0 +1,37 @@ +package com.kwan.springbootkwan.entity; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.*; + +/** + * 数据校验 + * + * @author : qinyingjie + * @version : 2.2.0 + * @Size 示一个字符串的长度或者一个集合的大小,必须在某一个范围中; min 参数表示范围的下限; max参数表示范围的上限; message 表示校验失败时的提示信息。 + * @NotNull 注解表示该字段不能为空。 + * @DecimalMin 注解表示对应属性值的下限,@DecimalMax 注解表示对应属性值的上限 + * @Email 注解表示对应属性格式是一个 Email + * @date : 2022/12/20 09:00 + */ +@Data +public class Student { + @ApiModelProperty(value = "主键") + private Integer id; + @ApiModelProperty(value = "姓名") + @Size(min = 5, max = 10, message = "{user.name.size}") + private String name; + @ApiModelProperty(value = "地址") + @NotNull(message = "{user.address.notnull}") + private String address; + @ApiModelProperty(value = "年龄") + @DecimalMin(value = "1", message = "{user.age.size}") + @DecimalMax(value = "200", message = "{user.age.size}") + private Integer age; + @ApiModelProperty(value = "邮箱") + @Email(message = "{user.email.pattern}") + @NotNull(message = "{user.email.notnull}") + private String email; +} diff --git a/src/main/resources/ValidationMessages.properties b/src/main/resources/ValidationMessages.properties new file mode 100644 index 0000000000000000000000000000000000000000..268e77715499f4e75a9de13f445b507a56c61b0d --- /dev/null +++ b/src/main/resources/ValidationMessages.properties @@ -0,0 +1,5 @@ +user.name.size=用户名的长度在5到10个字符之间 +user.address.notnull=用户地址不能为空 +user.age.size=年龄输入不正确 +user.email.notnull=邮箱不能为空 +user.email.pattern=不正确的电子邮件格式 \ No newline at end of file diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 84243657fc5b90d1742fc6c11660ec68fa16712c..1de9fb41ed1564582e3a5cec15342da1b8bcc57a 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,11 +1,24 @@ server: port: 8761 + servlet: + encoding: + force: true + charset: UTF-8 + enabled: true swagger: enable: true #兼容swagger配置 spring: + #项目启动时创建数据表的 SQL 脚本,该脚本由 Spring Batch 提供 + #spring.datasource.schema=classpath:/org/springframework/batch/core/schema-mysql.sql + # 在项目启动时执行建表 SQL + batch: + initialize-schema: always + # 禁止 Spring Batch 自动执行,在 SpringBoot 中,默认情况,当项目启动时就会执行配置好的批理操作,添加了该配置后则不会自动执行,而需要用户手动触发执行 + job: + enabled: false mail: host: smtp.qq.com # 发送者的邮箱账号 diff --git a/src/main/resources/data.csv b/src/main/resources/data.csv new file mode 100644 index 0000000000000000000000000000000000000000..7323856112b15ffed6b1b19bbc30352f489a4aa0 --- /dev/null +++ b/src/main/resources/data.csv @@ -0,0 +1,5 @@ +id,username,address,gender +1,张三,成都,男 +2,李四,深圳,女 +3,张三,成都,男 +4,李四,深圳,女 \ No newline at end of file