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

news2024/10/10 12:14:44

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=boot

logging.level.org.springframework.security=INFO
spring.thymeleaf.cache=false

spring.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
	@GeneratedValue
	private Long id;
	
	private String username;
	private String password;
	
	
	@ManyToManay(cascade = {CascadeType.REFRESH},fetch=FetchType.EAGER)
	private List<SysRole> roles;

	@Override
	public 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;
	}

	@Override
	public boolean isAccountNonExpired(){
		return true;
	}

	@Override
	public boolean isAccountNonLocked(){
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired(){
		return true;
	}

	@Override
	public boolean isEnabled(){
		return true;
	}

	//省略get\set方法
}
@Entity
public class SysRole{
	
	@Id
	@GeneratedValue
	private 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{//自定义需要实现该接口
	
	@Autowired
	SysUserRepository userRepository;

	@Override
	public UserDetails loadUserByUsername(){//获得用户,直接返回给SprngSecurity
		SysUser 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 将会自动跳转到登录页面
	@Override
	public 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{
	
	@Bean
	UserDetailsService customUserService(){//注册该bean
		return new CustomUserService();
	}

	/**
		用户认证
		①、添加内存中的用户,并且可以给用户指定角色权限
		auth.inMemoryAuthentication().withUser("wyf").password("wyf")
			.roles("ROLE_ADMIN").and().withUser("wisely").password("wisely").roles("ROLE_USER");

		②、JDBC中的用户直接指定dataSource即可
		这里的SpringSecurity默认了数据库接口,通过jdbcAuthentication源码可以得出JdbcDaoImpl中定义了默认的用户及角色权限
		
		@Autowired
		DataSource dataSource;
		@Override
		protected void configure(AuthenticationManagerBuilder auth)throws Exception{
			auth.jdbcAuthentication().dataource(dataSource);
			//也可以i定义查询用户和权限的SQL
			auth.jdbcAuthentication().dataource(dataSource)
				.usersByUsernameQuery("select username,password,true from myusers where username=?")
				.authoritiesByUsername("select username,role from roles where username=?");
		}
		
	*/
	//③、通用用户,实现UerDetailsService接口,以上JDBC用户和内存用户就是其实现
	@Override
	protected 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(); //其余所有请求都需要认证登录后才可以访问
	*/
	@Override
	protected 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>{
	
	@Override
	public 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;

	@Override
	public void afterProperitesSet()throws Exception{//使用JSR-303校验数据
		ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
		validator = validatorFactory.usingContext().getValidator();
	}

	@Override
	public 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;

	@Override
	public void beforeJob(JobExecution jobExecution){
		startTime = System.currentTimeMillis();
		System.out.println("任务处理开始");
	}

	@Override
	public 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{
	
	@Bean
	public 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;
	}

	@Bean
	public ItemProcessor<Person,Person> processor(){
		CsvItemProcessor processor = new CsvItemProcessor();//使用自定义的ItemProcessor的实现CsvItemProcessor
		processor.setValidator(csvBeanValidator());//为processor指定校验器为CsvBeanValidator
		return processor;
	}

	@Bean
	public 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;
	}

	@Bean
	public JobRepository jobRepository(DataSource dataSource,PlatformTransactionManager transactionManager)throws Exception{
		
		JobRepositoryFactoryBean jobRepositoryFactoryBean = new JopRepositoryFactoryBean();
		jobRepositoryFactoryBean.setDataSource(dataSource);
		jobRepositoryFactoryBean.setTransactionManager(transactionManager);
		jobRepositoryFactoryBean.setDatabaseType("oracle");
		return jobRepositoryFactoryBean.getObject();
	}

	@Bean
	public SimpleJobLauncher jobLauncher(DataSource dataSource,PlatformTransactionManager transactionManager){
		
		SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
		jobLauncher.setJobRepository(jobRepository(dataSource,transactionManager));
		return jobLauncher;
	}

	@Bean
	public Job importJob(JobBuilderFactory jobs,Step s1){
		
		return jobs.get("importJob")
			.incrementer(new RunIdIncrementer())
			.flow(s1)//为Job指定Step
			.end()
			.listener(csvJobListener())//绑定监听器
			.build();
	}

	@Bean
	public 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();
	}

	@Bean
	public CsvJobListener csvJobListener(){
		
		return new CsvJobListener();
	}
	
	@Bean
	public 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{
	
	@Autowired
	JobLauncher jobLauncher;

	@Autowired
	Job 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{
	
	@Override
	public Message createMessage(Session session) throws JMSException{
		return session.createTextMessage("测试消息");
	}
}

④、消息发送及目的地

@SpringBootApplication
public class ChApplication implements CommandLineRunner{//SpringBoot提供的接口
	
	@Autowired
	JmsTemplate jmsTemplate;//注入SpringBoot配置好的bean

	public static void main(String[] args){
		SpringApplication.run(ChApplication.class,args);
	}

	@Override
	public 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{
	
	@Autowired
	RabbitTemplate rabbitTemplate;//注入SpringBoot配置好的

	public static void main(String[] args){
		SpringApplication.run(ChApplication.class,args);
	}

	@Bean
	public Queue wiselyQueue(){
		return new Queue("my-queue");//定义目的地队列
	}

	@Override
	public 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类型SyndEntry
									mapping ->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.coloradmin.cn/o/2195271.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【瑞昱RTL8763E】刷屏

1 显示界面填充 用户创建的各个界面在 rtk_gui group 中。各界面中 icon[]表对界面进行描述&#xff0c;表中的每个元素代表一 个显示元素&#xff0c;可以是背景、小图标、字符等&#xff0c;UI_WidgetTypeDef 结构体含义如下&#xff1a; typedef struct _UI_WidgetTypeDef …

每年每门学科排名第一的学生 和每年总成绩都有所提升的学生

一张学生成绩表(student_scores)&#xff0c;有year-学年&#xff0c;subject-课程&#xff0c;student-学生&#xff0c;score-分数这四个字段&#xff0c;请完成如下问题&#xff1a; 问题1&#xff1a;每年每门学科排名第一的学生 问题2&#xff1a;每年总成绩都有所提升的…

【STM32 HAL库】MPU6050 DMP库移植 与 自检失败的处理

【STM32 HAL库】MPU6050 DMP库移植 与 自检失败的处理 本文参考移植步骤文件配置代码修改inv_mpu.cinv_mpu.hinv_mpu_dmp_motion_driver.c 使用 自检失败怎么处理ret -1改正DEBUG过程 ret -9改正DEBUG过程 本文参考 B站 CSDN 移植步骤 文件配置 新建一个 dmp 文件夹 并将…

【斯坦福CS144】Lab1

一、实验目的 1.实现一个流重组器——一个将字节流的小块 &#xff08;称为子串或段 &#xff09;按正确顺序组装成连续的字节流的模块&#xff1b; 2.深入理解 TCP 协议的工作方式。 二、实验内容 编写一个名为"StreamReassembler"的数据结构&#xff0c;它负责…

【Nacos入门到实战十四】Nacos配置管理:集群部署与高可用策略

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

原神5.1前瞻网页HTML+CSS+JS

这篇文章主要是总结一下我在制作页面的时候用到的一些技术以及经验总结&#xff0c;博主也是第一次写网页&#xff0c;代码也是在不断地“进化”&#xff0c;哪里写的不好大家可以随意指出。 下面就是一些经验总结&#xff0c;如果想看具体效果我这里也不好展示&#xff0c;需要…

pytorch导入数据集

1、概念&#xff1a; Dataset&#xff1a;一种数据结构&#xff0c;存储数据及其标签 Dataloader&#xff1a;一种工具&#xff0c;可以将Dataset里的数据分批、打乱、批量加载并进行迭代等 &#xff08;方便模型训练和验证&#xff09; Dataset就像一个大书架&#xff0c;存…

QSerialPort 串口通信示例

之前使用过MFC写过串口通信的示例&#xff0c;今年学了Qt&#xff0c;特意使用Qt写了串口通信的示例&#xff0c;发现比MFC要容易一些&#xff0c; MFC串口示例如下&#xff1a; Qt示例如下&#xff1a; Qt这个做的很简单&#xff0c;主要还是想验证一下api&#xff0c; 核心…

今日指数day8实战补充(上)

1.用户管理 1.多条件综合查询 1.1 多条件综合查询接口说明 1&#xff09;原型效果 2&#xff09;接口说明 功能描述&#xff1a;多条件综合查询用户分页信息&#xff0c;条件包含&#xff1a;分页信息 用户创建日期范围 服务路径&#xff1a;/api/users 服务方法&#xff1…

Linux的Tomcat安装部署

1.下载jdk11 java11的官方URL 此时进入可能会有登录注册,挺简单的,注册登录就好 2.上传到Linux 3.解压 命令: tar -zxvf /root/linux.jdk/jdk-11.0.24_linux-x64_bin.tar.gz 4.移动解压文件夹到新建文件夹 新建文件夹: mkdir -p /export/server 移动命令: mv jdk-11.0…

联想服务器配置阵列、安装操作系统

文章目录 [toc]1.配置阵列2.制作启动盘3.安装系统 1.配置阵列 1.根据提示进入BIOS设置&#xff08;F1&#xff09; 2.系统设置 3.存储 4.第四步可以看到raid卡信息 5.Main Menu 6.Configuration Management 7.Create Virtual Drive 8.Select RAID Level raid5 9.Select Drives…

透明物体的投射和接收阴影

1、让透明度测试Shader投射阴影 &#xff08;1&#xff09;同样我们使用FallBack的形式投射阴影&#xff0c;但是需要注意的是&#xff0c;FallBack的内容为&#xff1a;Transparent / Cutout / VertexLit&#xff0c;该默认Shader中会把裁剪后的物体深度信息写入到 阴影映射纹…

降重秘籍:如何利用ChatGPT将重复率从45%降至10%以下?

AIPaperGPT&#xff0c;论文写作神器~ https://www.aipapergpt.com/ 重复率高达45%&#xff1f;很多人一查论文的重复率&#xff0c;瞬间想“完了&#xff0c;这次真的要重写了”。但其实不用这么绝望&#xff01;有了ChatGPT&#xff0c;降重真的没那么难。今天就教你几招&a…

VGG16模型实现MNIST图像分类

MNIST图像数据集 MNIST&#xff08;Modified National Institute of Standards and Technology&#xff09;是一个经典的机器学习数据集&#xff0c;常用于训练和测试图像处理和机器学习算法&#xff0c;特别是在数字识别领域。该数据集包含了大约 7 万张手写数字图片&#xf…

wsl环境下安装MySQL5.7

安装操作需root权限&#xff1a; 1-通过 sudo su - &#xff0c;切换到root用户。 2-在每一个命令前加上sudo&#xff0c;临时提升权限 1、下载apt仓库文件 wget https://dev.mysql.com/get/mysql-apt-config_0.8.12-1_all.deb 安装包是.deb的文件2、配置仓库&#xff0c;使…

MyBatis 批量插入方案

MyBatis 批量插入 MyBatis 插入数据的方法有几种&#xff1a; for 循环&#xff0c;每次都重新连接一次数据库&#xff0c;每次只插入一条数据。 在编写 sql 时用 for each 标签&#xff0c;建立一次数据库连接。 使用 MyBatis 的 batchInsert 方法。 下面是方法 1 和 2 的…

Linux防火墙-案例(一)filter表

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们经过上小章节讲了Linux的部分进阶命令&#xff0c;我们接下来一章节来讲讲Linux防火墙。由于目前以云服务器为主&#x…

51单片机的水位检测系统【proteus仿真+程序+报告+原理图+演示视频】

1、主要功能 该系统由AT89C51/STC89C52单片机LCD1602显示模块水位传感器继电器LED、按键和蜂鸣器等模块构成。适用于水位监测、水位控制、水位检测相似项目。 可实现功能: 1、LCD1602实时显示水位高度 2、水位传感器采集水位高度 3、按键可设置水位的下限 4、按键可手动加…

动手学大模型应用开发之大模型简介

动手学大模型应用开发之大模型简介 主要学习目标什么是大语言模型大模型的能力和特点涌现能力作为基座模型支持多元应用的能力支持对话作为统一入口的能力大模型特点 常见大模型ChatGpt通义千问 LangChainLangChain的核心模块 总结相关学习链接 主要学习目标 学习如何进行大模…

【AI知识点】激活函数(Activation Function)

激活函数&#xff08;Activation Function&#xff09; 是神经网络中的一个关键组件&#xff0c;负责将输入的线性组合转化为非线性输出。它赋予神经网络模型以复杂的表达能力&#xff0c;使其能够处理非线性问题&#xff0c;比如分类、图像识别和自然语言处理等任务。 1. 激活…