当前位置: 首页 > news >正文

SpringBoot企业级开发(SpringSecurity安全控制+pringBatch批处理+异步消息+系统集成SpringIntegration)

Spring Security

多个过滤器来实现所有安全的功能,只需要注册一个特殊的DelegatingFilterProxy过滤器到WebAppliationInitializer即可
实际使用中需要让自己的Initializer类继承AbstractSecurity WebApplicationInitializer抽象类即可。

AbstractSecurityWebApplicationInitializer实现了WebApplicationInitializer接口,并通过onStartup方法调用

①、依赖

spring-boot-starter-data-jpa
spring-boot-starter-security
spring-boot-starter-thymeleaf
ojdbc6
thymeleaf-extras-springsecurity4

②、配置

spring.datasource.drivuerClassName=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc\:oracle\:thin\:@localhost\:1521\:xe
spring.datasource.username=boot
spring.datasource.password=bootlogging.level.org.springframework.security=INFO
spring.thymeleaf.cache=falsespring.jpa.hibernate.ddl-auto=update #自动生成用户表、角色表以及关联表
spring.jpa.show-sql=true

将bootstrap.min.css放置在src/main/resources/static/css下,此路径默认不拦截

③、用户和角色

@Entity
public class SysUser implements UserDetails{//实现该接口,用户实体即为Spring Security使用的用户private static final long serialVersionUID = 1L;@Id@GeneratedValueprivate Long id;private String username;private String password;@ManyToManay(cascade = {CascadeType.REFRESH},fetch=FetchType.EAGER)private List<SysRole> roles;@Overridepublic Colletion<? extends GrantedAuthority> getAuthorities(){//将用户的角色作为权限List<GrantedAuthority> auths = new ArrayList<>();List<SysRole> roles = this.getRoles();for(SysRole role:roles){auths.add(new SimpleGrantedAuthority(role.getName()));}return false;}@Overridepublic boolean isAccountNonExpired(){return true;}@Overridepublic boolean isAccountNonLocked(){return true;}@Overridepublic boolean isCredentialsNonExpired(){return true;}@Overridepublic boolean isEnabled(){return true;}//省略get\set方法
}
@Entity
public class SysRole{@Id@GeneratedValueprivate Long id;private String name;//省略getter、setter方法
}

④、Dao数据访问

public interface SysUserRepository extends JpaRepository<SysUser,Long>{SysUser findByUsername(String username);
}

⑤、自定义Service服务

public class CustomUserService implements UserDetailsService{//自定义需要实现该接口@AutowiredSysUserRepository userRepository;@Overridepublic UserDetails loadUserByUsername(){//获得用户,直接返回给SprngSecuritySysUser user = userRepository.findUsername(username);if(user == null){throw new UsernameNotFoundException("用户名不存在");}return user;}
}

⑥、Configuration配置SpringMVC

注册访问/login转向login.html

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter{//访问http://localhost:8080 将会自动跳转到登录页面@Overridepublic void addViewController(ViewControllerRegistry registry){registry.addViewController("/login").setViewName("login");}
}

扩展Spring Security配置,所有请求需要认证登录后才能方法(登录和注销)

SpringBoot针对Spring Security的自动配置通过SecurityAutoConfiguration和SecurityProperties来配置

SpringBoot做了很多配置,需要扩展配置只需要继承WebSecurityConfigurerAdapter类,无需@EnableWebSecurity注解

//相关的安全配置
@Configuration
//@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{@BeanUserDetailsService customUserService(){//注册该beanreturn new CustomUserService();}/**用户认证①、添加内存中的用户,并且可以给用户指定角色权限auth.inMemoryAuthentication().withUser("wyf").password("wyf").roles("ROLE_ADMIN").and().withUser("wisely").password("wisely").roles("ROLE_USER");②、JDBC中的用户直接指定dataSource即可这里的SpringSecurity默认了数据库接口,通过jdbcAuthentication源码可以得出JdbcDaoImpl中定义了默认的用户及角色权限@AutowiredDataSource dataSource;@Overrideprotected void configure(AuthenticationManagerBuilder auth)throws Exception{auth.jdbcAuthentication().dataource(dataSource);//也可以i定义查询用户和权限的SQLauth.jdbcAuthentication().dataource(dataSource).usersByUsernameQuery("select username,password,true from myusers where username=?").authoritiesByUsername("select username,role from roles where username=?");}*///③、通用用户,实现UerDetailsService接口,以上JDBC用户和内存用户就是其实现@Overrideprotected void configure(AuthenticationManagerBuilder auth)throws Exception{auth.userDetailsService(customUserServie());//添加自定义认证,注册}/**请求授权,匹配了一下请求路径,需要针对当前用户的信息对请求路径进行安全处理Ⅰ、antMatchers 使用Ant风格的路径皮喷Ⅱ、regexMatchers 使用正则表达式匹配路径Ⅲ、anyRequest 匹配所有路径安全处理方法:access(String) SpringEL表达式结果为true时可访问anonymous() 匿名访问denyAll() 用户不能访问fullyAuthenticated() 用户完全认证可访问(非remeber me下自动登录)hasAnyAuthority(String..) 如果用户有参数,则其中任一权限可访问hasAnyRole(String..) 如果用户有参数,则其中任一角色可访问hasAuthority(String) 如果用户有参数,则其权限可访问hasIpAddress(String) 如果用户来自参数中的IP则可访问hasRole(String) 若用户有参数中的角色可访问permitAll() 用户可任意访问rememberMe() 运行通过remember-me登录的用户访问authenticated() 用户登录后可访问http.authorizeRequests().antMatchers("/admin/**").hasRole("ROLE_ADMIN").antMatchers("/user/**").hasAnyRole("ROLE_ADMIN","ROLE_USER").anyRequst().authenticated(); //其余所有请求都需要认证登录后才可以访问*/@Overrideprotected void configure(HttpSecurity http) throws Exception{http.authorizeRequests()//开始请求权限配置.anyRequest().authenticated()//所有请求需要认证登陆后才能访问.and().formLogin() //定制登录操作.loginPage("/login")//登录页面的访问地址.defaultSuccessUrl("/index")//指定登录成功后转向的页面.failureUrl("/login?error")//登录失败转向的页面.permitAll()//定制登录行为,登录页面可以任意访问.and().rememberMe()//开启cookie存储用户信息.tokenValiditySeconds(1209600)//指定cookie有效期2个星期.key("myKey")//指定cookie中的私钥.and().logout().logout("/costom-logout")//指定注销的URL路径.logoutSuccessUrl("/logout-success")//指定注销成功后转向的页面.permitAll();//定制注销行为,注销请求可任意访问}
}

⑦、页面

<!--Thymeleaf提供了Spring Security的标签支持-->
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">

获得当前用户名
sec:authentication=“name”

当前用户觉得为ROLE_ADMIN时才现实标签内容
sec:authorize=“hasRole(‘ROLE_ADMIN’)”

注销的默认路径/logout,需要通过POST请求提交
th:action=“@{/logout}” method=“post”

Spring Batch

处理大量数据的框架,用来读取大量数据,然后进行一定处理后输出成指定的形式

①、依赖

spring-boot-starter-jdbc
spring-boot-starter-batch(因为使用Oracle,所以排除hsqldb)
spring-boot-starter-web
ojdbc6
hibernate-validator 数据校验

数据准备:
src/main/resources/people.csv中添加 jordan,23,非汉族,芝加哥 等多条类似的数据
数据表sql
id name age nation address

②、实体类

public class Person{@Size(max=4,min=2) //使用JSR-303校验数据private String name;private int age;private String nation;private String address;//省略get和set方法
}

③、数据处理及校验

public class CsvIntemProcessor extemds ValidatingItemProcessor<Person>{@Overridepublic Person process(Person item) throws ValidationException{super.process(item);//调用自定义校验器if(item.getNation().equals("汉族")){item.setNation("01");}else{item.setNation("02");}return item;}
}
public class CsvBeanValidator<T> implements Validator<T>,InitializingBean{private javax.validation.Validator validator;@Overridepublic void afterProperitesSet()throws Exception{//使用JSR-303校验数据ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();validator = validatorFactory.usingContext().getValidator();}@Overridepublic void validate(T value)throws ValidationException{//使用Validator的validate的方法校验数据Set<ConstraintViolation<T>> constraintViolations = validator.validate(value);if(constraitViolations.size()>0){StringBuilder message = new StringBuilder();for(ConstraintVilation<T> constraintViolation : constraintViolations){message.append(constraintViolation.getMessage() + "\n");}throw new ValidationException(message.toString());}}
}

④、Job监听

public class CsvJobListener implements JobExecutionListener{long startTime;long endTime;@Overridepublic void beforeJob(JobExecution jobExecution){startTime = System.currentTimeMillis();System.out.println("任务处理开始");}@Overridepublic void afterJod(JobExecution jobExecution){startTime = System.currentTimeMillis();System.out.println("任务处理结束");System.out.println("耗时:"+(endTime-startTime)+"ms");}
}

⑤、配置

  • JobRepository 用来注册Job容器
  • JobLauncher 用来启动Job的接口
  • Job 实际执行的任务,包含一个或多个Step
  • Step 包含ItemReader ItemProcessor和ItemWriter
  • ItemReader 用来读取数据的接口
  • ItemProcessor 用来处理数据的接口
  • ItemWriter 用来输出数据的接口
@Configuration
@EnableBatchProcessing //开启批处理支持
public class CsvBatchConfig{@Beanpublic ItemReader<Person> reader()throws Exception{FlatFileItemReader<Person> reader = new FlatFileItemReader<>();//读取文件reader.setResource(new ClassPathResource("people.csv"));//设置csv文件路径reader.setLineMapper(new DefautLineMapper<Person>(){{setLineTokenizer(new DelimitedLineTokenizer(){{setNames(new String[]{"name","age","nation","address"});}});setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>(){{setTargetType(Person.class);}});}});return reader;}@Beanpublic ItemProcessor<Person,Person> processor(){CsvItemProcessor processor = new CsvItemProcessor();//使用自定义的ItemProcessor的实现CsvItemProcessorprocessor.setValidator(csvBeanValidator());//为processor指定校验器为CsvBeanValidatorreturn processor;}@Beanpublic ItemWriter<Person> write(DataSource dataSource){//SpringBoot让已有的容器bean,注入JdbcBatchItemWriter<Person> writer = new JdbcBatchItemWriter<>();//使用JDBC批处理的jdbcBatchItemWriter来写数据到数据库writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>());String sql = "insert into person"+"(id,name,age,nation,address)"+"values(hibernate_sequence.nextval,:name,:age,:nation,:address)";wirter.setSql(sql);//设置要执行批处理的SQL语句writer.setDataSource(dataSource);return writer;}@Beanpublic JobRepository jobRepository(DataSource dataSource,PlatformTransactionManager transactionManager)throws Exception{JobRepositoryFactoryBean jobRepositoryFactoryBean = new JopRepositoryFactoryBean();jobRepositoryFactoryBean.setDataSource(dataSource);jobRepositoryFactoryBean.setTransactionManager(transactionManager);jobRepositoryFactoryBean.setDatabaseType("oracle");return jobRepositoryFactoryBean.getObject();}@Beanpublic SimpleJobLauncher jobLauncher(DataSource dataSource,PlatformTransactionManager transactionManager){SimpleJobLauncher jobLauncher = new SimpleJobLauncher();jobLauncher.setJobRepository(jobRepository(dataSource,transactionManager));return jobLauncher;}@Beanpublic Job importJob(JobBuilderFactory jobs,Step s1){return jobs.get("importJob").incrementer(new RunIdIncrementer()).flow(s1)//为Job指定Step.end().listener(csvJobListener())//绑定监听器.build();}@Beanpublic Step step1(StepBuilderFactory stepBuilderFactory,ItemReader<Person> reader,ItemWriter<Person> writer,ItemProcessor<Person,Person> processor){return stepBuilderFactory.get("step1").<Person,Person>chunk(65000)//批处理,每次提交65000条数据.reader(reader)//为step绑定那个reader.processor(processor)//给step绑定processor.writer(writer)//给step绑定writer.build();}@Beanpublic CsvJobListener csvJobListener(){return new CsvJobListener();}@Beanpublic Validator<Person> csvBeanValidator(){return new CsvBeanValidator<Person>();}
}

⑥、运行

SpringBoot会自动初始化SpringBatch数据库,并将CSV中的数据导入到数据库中
在这里插入图片描述
监听器效果
在这里插入图片描述
数据已导入且做转换处理
在这里插入图片描述
在这里插入图片描述
⑦、手动触发任务

注释调CsvBatchConfig类的@Configuration注解,让此类不在起效

新建TriggerBatchConfig配置类,内容同CsvBatchConfig完全保持一致

修改定义ItemReader

@Bean
@StepScope
public FlatFileItemReader<Person> reader(@Value("#{jobParameters['input.file.name']}") String pathToFile)throws Exception{FlatFileItemReader<Person> reader = new FlatFileItemReader<>();//reader.setResource(new ClassPathResource(pathToFile));//reader.setLineMapper(new DefautLineMapper<Person>(){{setLineTokenizer(new DelimitedLineTokenizer(){{setNames(new String[]{"name","age","nation","address"});}});setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>(){{setTargetType(Person.class);}});}});return reader;
}

控制定义

@RestController
public class DemoController{@AutowiredJobLauncher jobLauncher;@AutowiredJob importJob;public JobParameters jobParameters;@RequestMapping("/imp")public String imp(String fileName)throws Exception{String path = fileName + ".csv";jobParameters = new JobParametersBuilder().addLong("time",System.currentTimeMillis()).addString("input.file.name",path).toJobParameters();jobLauncher.run(importJob,jobParameters);return "ok";}}

此时如果关闭SpringBoot为我们自动执行了Job的配置,在application.properties里使用如下代码
spring.batch.job.enabled=false

访问http://localhost:8080/imp?fileName=people可获得相同的数据导入效果
在这里插入图片描述

异步消息

Spring通过@EnableJms @EnableRabbit开启支持

SpringBoot自动开启了@EnableJms @EnableRabbit

JMS

①、安装ActiveMQ

docker run -d -p 61616:61616 -p 8161:8161 cloudesire/activemq

其中61616是消息代理的端口
8161是ActiveMQ管理界面端口 http://localhost:8161打开ActiveMQ的管理界面 账号密码admin/admin

也可以将ActiveMQ内嵌在程序里依赖activemq-broker

②、依赖

spring-boot-starter
spring-jms
activemq-client

application.properties配置ActiveMQ消息代理
spring.activemq.broker-url=tcp://localhost:61616

③、消息定义

public class Msg implements MessageCreator{@Overridepublic Message createMessage(Session session) throws JMSException{return session.createTextMessage("测试消息");}
}

④、消息发送及目的地

@SpringBootApplication
public class ChApplication implements CommandLineRunner{//SpringBoot提供的接口@AutowiredJmsTemplate jmsTemplate;//注入SpringBoot配置好的beanpublic static void main(String[] args){SpringApplication.run(ChApplication.class,args);}@Overridepublic void run()throws Exception{jmsTemplate.send("my-destination",new Msg());//向my-destination目的地发送Msg的消息}
}

⑤、消息监听

@Component
public class Receiver{@JmsListener(destination="my-destination")//Spring4.1新特性,监听的目的地,接收消息public void receiveMesssage(String message){Systemm.out.println("接收到:<" + message +">");}
}

⑥、运行
在这里插入图片描述

AMQP

①、安装RabbitMQ

先下载安装erlang http://www.erlang.org/download.html
下载RabbitMQ https://www.rabbitmq.com/download.html

docker run -d -p 5672:5672 -p 15672:15672 rabbitmq:3-management

5672属于消息代理的端口
15672属于管理界面的端口 http://localhost:15672 guest/guest

②、依赖

spring-boot-starter-amqp

SpringBoot默认Rabbit注解为localhost、端口号5672
无需为SpringBoot的application.properties配置RabbitMQ的连接信息

③、发送信息及目的地

@SpringBootApplication
public class ChApplication implements CommandLineRunner{@AutowiredRabbitTemplate rabbitTemplate;//注入SpringBoot配置好的public static void main(String[] args){SpringApplication.run(ChApplication.class,args);}@Beanpublic Queue wiselyQueue(){return new Queue("my-queue");//定义目的地队列}@Overridepublic void run(String... args)throws Exception{//向队列my-queue发送消息rabbitTemplate.convertAndSend("my-queue","来自RabbitMQ的问候");}}

④、消息监听

@Component
public class Receiver{@RabbitListener(queues = "my-queue")public void receiveMessage(String message){System.out.println("Received<" + message + ">");}
}

⑤、运行

系统集成Spring Integration

解决不同系统之间交互的问题,通过异步消息驱动来达到系统交互时系统之间的松耦合。

①、读取https://spring.io/blog.atom的新闻聚合文件,atom是一种xml文件,且格式是固定的

将读取到的消息通过分类(Category),将消息转到不同的消息通道
将分类为releases和engineering的消息写入磁盘,将分类为news的消息通过邮件发送
在这里插入图片描述

②、依赖

spring-boot-starter-integration
spring-boot-starter-mail

Spring Integration对atom及mail的支持:
spring-integration-feed
spring-integration-mail

②、读取流程(入口类完成)

@Value("https://spring.io/blog.atom")//获得资源
Resource resource@Bean(name=PollerMetadata.DEFAULT_POLLER)
public PollerMetadata poller(){//配置默认的轮询方式return Pollers.fixedRate(500).get();
}@Bean
public FeedEntryMessageSource feedMessageSource() throws IOException{//FeedEntryMessageSource messageSource = new FeedEntryMessageSource(resource.getURL(),"news");return messageSource;
}@Bean
public IntegrationFlow myFlow() throws IOException{return IntegrationFlows.from(feedMessageSource())//流程从from 方法开始.<SyndEntry,String> route(payload ->payload.getCategories().get(0).getname(),//选择路由,消息体payload类型SyndEntrymapping ->mapping.channelMapping("releases","releasesChannel").channelMapping("engineering","engineeringChannel")//不同分类的值转向不同的消息通道.channelMapping("news","newsChannel")).get();//获得IntegrationFlow实体,配置为Spring的Bean
}

③、release流程

@Bean
public IntegrationFlow releasesFlow(){return IntegrationFlows.from(MessageChannels.queue("releasesChannel",10)) //从消息通道releasesChannel开始获取数据.<SyndEntry,String> transform(payload->"《" + payload.getTitle()+"》"+payload.getLink()+getProperty("line.separator"))//数据转换.handle(Files.outboundAdapter(new File("e:/springblog"))//file出站适配器.fileExistsMode(FileExistsMode.APPEND).charset("UTF-8").fileNameGenerator(message -> "releases.txt").get()).get();}

④、engineering流程

@Bean
pubic IntegratonFlow engineeringFlow(){return IntegrationFlows.from(MessageChannels.queue("engineeringChannel",10)).<SyndEntry,String> transform(e->"《"+e.getTitle()+"》"+e.getLink()+getProperty("line.separator")).handle(Files.outboundAdapter(new File("e:/springblog")).fileExistsMode(FileExistsMode.APPEND).charset("UTF-8").fileNameGenerator(message->"engineering.txt").get()).get();
}

⑤、news流程

@Bean
public IntegrationFlow newsFlow(){return IntegrationFlows.from(MessageChannels.queue("newsChannel",10)).<SyndEntry,String> transform(payload->"《"+payload.getTitle()+"》"+payload.getLink()+getProperty("line.separator")).enrichHeaders(Mail.headers() //增加消息头信息.subject("来自Spring的新闻").to("wise-man@126.com").from("wisely-man@126.com"))//邮件发送的相关信息.handle(Mail.outboundAdapter("smtp.126.com")//邮件发送的出站适配器.port(25).protocol("smtp").credentials("wisely-man@126.com","****").javaMailProperties(p->p.put("mail.debug"),false)),e->e.id("smtpOut")).get();
}

⑥、运行

在这里插入图片描述
在这里插入图片描述
release.txt文件内容
在这里插入图片描述
邮箱接收结果
在这里插入图片描述


http://www.mrgr.cn/news/44475.html

相关文章:

  • 利用LLMs自动寻找量化投资策略
  • 医院管理新趋势:Spring Boot技术引领
  • 安卓如何实现双击触摸唤醒点亮屏幕功能-Android framework实战开发
  • mmdetection实战,训练自己的数据集
  • C语言复习概要(四)
  • 基于SpringBoot vue3 的山西文旅网java网页设计与实现
  • 国庆练习(Day24)
  • vscode提交修改Failed to connect to github.com port 443: Timed out
  • 一个典型的cmakelists.txt
  • 【星汇极客】单片机竞赛之2024睿抗机器人大赛-火线速递赛道(持续更新)
  • 向量数据库!AI 时代的变革者还是泡沫?
  • 产品经理内容分享(一):AI产品经理需必备那些能力
  • [Day 85] 區塊鏈與人工智能的聯動應用:理論、技術與實踐
  • 网络安全学习(记录学习过程)
  • 点餐小程序实战教程16餐厅管理
  • 低温无压烧结银在射频通讯上的5大应用
  • 【JavaEE】【多线程】进程与线程的概念
  • [Linux] 进程创建、退出和等待
  • 77寸OLED透明触摸屏有哪些应用场景
  • IL2CPP和Mono的区别