day11【首页数据显示和添加Redis缓存】
1 搭建项目前端环境(NUXT)
01-服务端渲染技术NUXT-初始化NUXT
一、服务端渲染技术NUXT
1、什么是服务端渲染
服务端渲染 又称SSR (Server Side Render)是在服务端完成页面的内容,而不是在客户端通过AJAX获取数据。
服务器端渲染(SSR)的优势主要在于:更好的 SEO ,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。
如果你的应用程序初始展示 loading 菊花图,然后通过 Ajax 获取内容 ,抓取工具并不会等待异步完成 后再进行页面内容的抓取。也就是说,如果 SEO 对你的站点至关重要,而你的页面又是异步获取内容,则你可能需要服务器端渲染(SSR)解决此问题。
另外,使用服务器端渲染,我们可以获得更快的内容到达时间(time-to-content),无需等待所有的 JavaScript 都完成下载并执行,产生更好的用户体验,对于那些「内容到达时间(time-to-content)与转化率直接相关」的应用程序而言,服务器端渲染(SSR)至关重要。
2、什么是NUXT
Nuxt.js 是一个基于 Vue.js 的轻量级应用框架, 可用来创建服务端渲染 (SSR) 应用,也可充当静态站点引擎生成静态站点应用,具有优雅的代码结构分层和热加载等特性。
官网网站:
https://zh.nuxtjs.org/
二、NUXT环境初始化
安装 nuxt.js:vue init nuxt-community/starter-template <你项目的名字>
运行Nuxt: npm install npm run dev
1、NUXT目录结构
(1)资源目录 assets
用于组织未编译的静态资源 如 LESS、SASS 或 JavaScript。
(2)组件目录 components
用于组织应用的 Vue.js 组件 。Nuxt.js 不会扩展增强该目录下 Vue.js 组件,即这些组件不会像页面组件那样有 asyncData 方法的特性。
(3)布局目录 layouts
用于组织应用的布局组件 。
(4)页面目录 pages
用于组织应用的路由及视图 。Nuxt.js 框架读取该目录下所有的 .vue 文件并自动生成对应的路由配置。
(5)插件目录 plugins
用于组织那些需要在 根vue.js应用 实例化之前需要运行的 Javascript 插件。
(6)nuxt.config.js 文件
nuxt.config.js 文件用于组织Nuxt.js 应用的个性化配置 ,以便覆盖默认配置。
三、幻灯片插件
1、安装插件
npm install vue-awesome-swiper
查看安装:
2、配置插件
在 plugins 文件夹下新建文件 nuxt-swiper-plugin.js,内容是
import Vue from 'vue'
import VueAwesomeSwiper from 'vue-awesome-swiper/dist/vue-awesome-swiper.js'
Vue.use(VueAwesomeSwiper)
在 nuxt.config.js 文件中配置插件
将 plugins 和 css节点 复制到 module.exports 节点下
plugins: [
{ src: '~/plugins/nuxt-swiper-plugin.js', ssr: false }
],
css: [
'swiper/dist/css/swiper.css'
]
02-首页静态效果整合和NUXT路由
一、页面布局
1、复制静态资源
将静态原型中的css、img、js、photo目录拷贝至assets目录下
2、定义布局
我们可以把页头和页尾提取出来,形成布局页
修改layouts目录下default.vue,从静态页面中复制首页,修改了原始文件中的资源路径为~/assets/,将主内容区域的内容替换成
3、定义首页面
(不包含幻灯片)
修改pages/index.vue:
修改了原始文件中的资源路径为~/assets/
4、幻灯片插件
script
export default {
data () {
return {
swiperOption: {
//配置分页
pagination: {
el: '.swiper-pagination'//分页的dom节点
},
//配置导航
navigation: {
nextEl: '.swiper-button-next',//下一页dom节点
prevEl: '.swiper-button-prev'//前一页dom节点
}
}
}
}
}
重新启动:npm run dev
访问网页:
二、路由
1、固定路由
(1)使用router-link构建路由,地址是/course
(2)在page目录创建文件夹course ,在 course目录创建index.vue
点击导航,测试路由
2、动态路由
(1)创建方式
如果我们需要根据id查询一条记录,就需要使用动态路由。NUXT的动态路由是以下划线开头的vue文件,参数名为下划线 后边的文件名
在pages下的course目录下创建_id.vue
三、封装axios
我们可以参考guli-admin将axios操作封装起来
下载axios ,使用命令:
npm install axios
创建utils文件夹,utils下创建request.js
import axios from 'axios'
// 创建axios实例
const service = axios.create({
baseURL: 'http://localhost:9001', // api的base_url
timeout: 20000 // 请求超时时间
})
export default service
03-名师页面静态效果整合
一、列表页面
创建 pages/teacher/index.vue
二、详情页面
创建 pages/teacher/_id.vue
修改资源路径为~/assets/
04-课程页面静态效果整合
一、列表页面
创建 pages/course/index.vue
二、详情页面
创建 pages/course/_id.vue
2 首页显示数据【前后端实现】
01-首页显示banner数据【后端】
1、在service模块下创建子模块service-cms
2、使用代码生成器生成banner代码
(1)创建crm_banner表
(2)生成代码
代码生成器:
3、配置application.properties
# 服务端口
server.port=8004
# 服务名
spring.application.name=service-cms
# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
#配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/atguigu/cmsservice/mapper/xml/*.xml
#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#配置mapper xml文件的路径
#如果需要在xml中写sql语句,需要添加两个配置,1在pom中 2在application中
mybatis-plus.mapper-locations=classpath:com/atguigu/educms/mapper/xml/*.xml
4、创建启动类
创建CmsApplication.java
package com.atguigu.educms;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan({"com.atguigu"}) //指定扫描位置
public class CmsApplication {
public static void main(String[] args) {
SpringApplication.run(CmsApplication.class, args);
}
}
@SpringBootApplication
@ComponentScan({"com.atguigu"}) //指定扫描位置
@MapperScan("com.atguigu.cmsservice.mapper")//操作数据库中有mapper,所以需要添加MapperScan扫描,添加到1配置类 或 2启动类
public class CmsApplication {
public static void main(String[] args) {
SpringApplication.run(CmsApplication.class, args);
}
}
二、创建banner服务接口
1、创建banner后台管理接口
banner后台分页查询、添加、修改、删除接口
@RestController
@RequestMapping("/educms/banneradmin")
@CrossOrigin
public class BannerAdminController {
@Autowired
private CrmBannerService bannerService;
//1 分页查询banner
@ApiOperation(value = "获取Banner分页列表")
@GetMapping("pageBanner/{page}/{limit}")
public R pageBanner(@PathVariable long page,
@PathVariable long limit){
Page crmBannerPage = new Page<>(page,limit);
bannerService.page(crmBannerPage,null);
return R.ok().data("items",crmBannerPage.getRecords()).data("total",crmBannerPage.getTotal());
}
//2 获取
@ApiOperation(value = "获取Banner")
@GetMapping("get/{id}")
public R get(@PathVariable String id){
CrmBanner crmBanner = bannerService.getBannerById(id);
return R.ok().data("item",crmBanner);
}
//3 添加
@ApiOperation(value = "新增Banner")
@PostMapping("save")
public R save(@RequestBody CrmBanner banner){
bannerService.saveBanner(banner);
return R.ok();
}
//4 修改
@ApiOperation(value = "修改Banner")
@PostMapping("update")
public R updateById(@RequestBody CrmBanner banner){
bannerService.updateBannerById(banner);
return R.ok();
}
//5 删除
@ApiOperation(value = "删除Banner")
@DeleteMapping("remove/{id}")
public R remove(@PathVariable String id){
bannerService.removeBannerById(id);
return R.ok();
}
}
CrmBannerServiceImpl.java
@Override
public CrmBanner getBannerById(String id) {
CrmBanner crmBanner = baseMapper.selectById(id);
return crmBanner;
}
@Override
public void saveBanner(CrmBanner banner) {
baseMapper.insert(banner);
}
@Override
public void updateBannerById(CrmBanner banner) {
baseMapper.updateById(banner);
}
@Override
public void removeBannerById(String id) {
baseMapper.deleteById(id);
}
2、创建banner前台查询接口
首页获取banner数据接口
@RestController
@RequestMapping("/educms/bannerfront")
@Api(description = "网站首页Banner列表")
@CrossOrigin
public class BannerFrontController {
@Autowired
private CrmBannerService bannerService;
@ApiOperation(value = "获取首页banner")
@GetMapping("getAllBanner")
public R index() {
List list = bannerService.selectIndexList ();
return R.ok().data("list", list);
}
}
@Override
public List selectIndexList() {
List crmBanners = baseMapper.selectList(null);
return crmBanners;
}
三、实现banner后台管理前端
实现banner后台的添加修改删除和分页查询操作,和其他后台管理模块类似
02-首页显示课程名师数据【后端】
(1)查询前2条baner数据
CrmBannerServiceImpl
@Override
public List selectIndexList() {
//根据id进行降序排列,显示排列之后的前两条记录
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.orderByDesc ("id");
//last方法,拼接sql语句
wrapper.last ("limit 2");
List crmBanners = baseMapper.selectList(null);
return crmBanners;
}
一、新建前端查询课程名师接口
1、在service-edu模块controller中创建包front
(1)查询最新前4条讲师数据
(2)查询最新前8条课程数据
@RestController
@RequestMapping("/eduservice/index")
@CrossOrigin
public class IndexController {
//查询前8条热门课程,查询前4条名师
@Autowired
private EduCourseService courseService;
@Autowired
private EduTeacherService teacherService;
@GetMapping("index")
public R index() {
//查询前8条热门课程
QueryWrapper courseQueryWrapper = new QueryWrapper<>();
courseQueryWrapper.orderByDesc("id");
courseQueryWrapper.last("limit 8");
List courseList = courseService.list(courseQueryWrapper);
//查询前4条名师
.......
return R.ok().data("courseList",courseList).data("teacherList",teacherList);
}
}
03-首页显示banner和课程名师数据【前端】
一、首页banner数据显示
1、创建api文件夹,创建banner.js文件
banner.js
import request from '@/utils/request'
export default {
//获取首页banner
getList() {
return request({
url: `/educms/bannerfront/getAllBanner`,
method: 'get'
})
}
}
2、在首页面引入,调用实现
框架的结构中,由两个页面构成,layouts/default.vue(头和尾)和pages/index.vue(首页)
import banner from "@/api/banner"
export default {
data () {
return {
bannerList: {},
swiperOption: {
//配置分页
pagination: {
el: '.swiper-pagination'//分页的dom节点
},
//配置导航
navigation: {
nextEl: '.swiper-button-next',//下一页dom节点
prevEl: '.swiper-button-prev'//前一页dom节点
}
}
}
},
created(){
this.initDataBanner()
},
methods: {
initDataBanner() {
banner.getList()
.then(response=>{
this.bannerList = response.data.data.list
})
}
}
}
3、在页面遍历显示banner
linkUrl">
:src="banner.imageUrl "
:alt="banner.title">
nginx访问规则配置:
二、首页显示课程和名师数据
1、创建api文件夹,创建index.js文件
index.js
import request from '@/utils/request'
export default {
//获取首页banner
getList() {
return request({
url: `/eduservice/index/index`,
method: 'get'
})
}
}
2、在首页面引入,调用实现
import banner from "@/api/banner"
import index from '@/api/index'
export default {
data () {
return {
courseList: {},
teacherList: {},
bannerList: {},
swiperOption: {
//配置分页
pagination: {
el: '.swiper-pagination'//分页的dom节点
},
//配置导航
navigation: {
nextEl: '.swiper-button-next',//下一页dom节点
prevEl: '.swiper-button-prev'//前一页dom节点
}
}
}
},
created(){
this.initDataBanner()
this.initDataObj()
},
methods: {
initDataBanner() {
banner.getList()
.then(response=>{
this.bannerList = response.data.data.list
})
},
initDataObj (){
index.getList()
.then(response=>{
this.teacherList = response.data.data. teacherList
this.courseList = response.data.data. courseList
})
}
}
}
3、在页面遍历显示课程和名师
热门课程
{{course.title}}
v-if="Number(course.price) === 0">
免费
v-else>
¥{{course.price}}
{{course.buyCount}} 人学习
|
{{course.viewCount}} 评论
全部课程
{{teacher.intro}}
class="c-999 f-fA"
>{{teacher.career}}
全部讲师
测试:http://localhost:3000
3 首页显示数据添加Redis缓存
需求:解决访问量大的问题
01-首页数据添加Redis缓存
一、Redis介绍
Redis是当前比较热门的NOSQL 系统之一,它是一个开源的使用ANSI c语言编写的key-value存储系统(区别于MySQL的二维表格的形式存储。)。和Memcache类似,但很大程度补偿了Memcache的不足。
和Memcache一样,Redis数据都是缓存在计算机内存中,不同的是,Memcache只能将数据缓存到内存中,无法自动定期写入硬盘,这就表示,一断电或重启,内存清空,数据丢失。所以Memcache的应用场景适用于缓存无需持久化的数据 。而Redis不同的是它会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,实现数据的持久化。
Redis的特点:
1,Redis读取的速度是110000次/s,写的速度是81000次/s;
2,原子 。Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
3,支持多种数据结构:string(字符串);list(列表);hash(哈希),set(集合);zset(有序集合)
4,持久化,集群部署
5,支持过期时间,支持事务,消息订阅
二、项目集成Redis
1、在common模块添加依赖
由于redis缓存是公共应用,所以我们把依赖与配置添加到了common模块下面,在common模块pom.xml下添加以下依赖
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
2.6.0
2、在service-base模块添加redis配置类
RedisConfig.java
package com.atguigu.servicebase;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@EnableCaching //开启缓存
@Configuration //配置类
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
RedisTemplate template = new RedisTemplate<>();
RedisSerializer redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setConnectionFactory(factory);
//key序列化方式
template.setKeySerializer(redisSerializer);
//value序列化
template.setValueSerializer(jackson2JsonRedisSerializer);
//value hashmap序列化
template.setHashValueSerializer(jackson2JsonRedisSerializer);
return template;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题),过期时间600秒
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600)) //设置数据过期时间600秒
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
3、在接口中添加redis缓存
由于首页数据变化不是很频繁,而且首页访问量相对较大,所以我们有必要把首页接口数据缓存到redis缓存中,减少数据库压力和提高访问速度。
改造service-cms模块首页banner接口,首页课程与讲师接口类似。
需要引入:
3.1 Spring Boot缓存注解
(1)缓存@Cacheable
根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;
如果缓存不存在,则执行方法,并把返回的结果存入缓存中。
一般用在查询方法上 。
查看源码,属性值如下:value(缓存名)和key(可选属性) 这两个值会构成保存到redis中的key的名称,Redis基于key-value进行存储的。
(2)缓存@CachePut
使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中 。
其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。
一般用在新增方法上。
查看源码,属性值如下:
(3)缓存@CacheEvict
使用该注解标志的方法,会清空指定的缓存 。
一般用在更新或者删除方法上
查看源码,属性值如下:
3.2 启动redis服务
在windows下安装redis:
解压安装: 将下载的Redis-x64-3.2.100.zip 解压到某个地址。
解压后目录如下:
启动命令:
通过cmd指定到该redis目录。
使用命令:redis-server.exe 启动服务
启动另一个cmd,在该redis目录下,使用命令:redis-cli.exe 启动客户端,连接服务器
出现这种效果,表明启动客户度成功。
3.3(虚拟机)连接redis服务可能遇到的问题
(1)关闭liunx防火墙
(2)找到redis配置文件, 注释一行配置
(3)如果出现下面错误提示
修改 protected-mode yes
改为
protected-mode no
3.4 banner接口改造
(1)在service-cms模块配置文件添加redis配置
#redis配置 windows采用本机127.0.0.1 虚拟机采用虚拟机的IP
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.database= 0
spring.redis.timeout=1800000
spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
#最大阻塞等待时间(负数表示没限制)
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0
(2)修改CrmBannerServiceImpl ,添加redis缓存注解
@Service
public class CrmBannerServiceImpl extends ServiceImpl implements CrmBannerService {
@Override
public CrmBanner getBannerById(String id) {
CrmBanner crmBanner = baseMapper.selectById(id);
return crmBanner;
}
@CacheEvict(value = "banner", allEntries=true)
@Override
public void saveBanner(CrmBanner banner) {
baseMapper.insert(banner);
}
@CacheEvict(value = "banner", allEntries=true)
@Override
public void updateBannerById(CrmBanner banner) {
baseMapper.updateById(banner);
}
@CacheEvict(value = "banner", allEntries=true)
@Override
public void removeBannerById(String id) {
baseMapper.deleteById(id);
}
@Cacheable(value = "banner", key = " 'selectIndexList'")
@Override
public List selectIndexList() {
//根据id进行降序排列,显示排列之后的前两条记录
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.orderByDesc("id");
//last方法,拼接sql语句
wrapper.last("limit 2");
List crmBanners = baseMapper.selectList(null);
return crmBanners;
}
}
(3)在redis添加了key
第一次查询执行了sql语句,再次获取页面没有执行sql语句,而是查询redis缓存中的数据。
查询:
(4)通过源码查看到key生成的规则
你可能感兴趣的:(day11【首页数据显示和添加Redis缓存】)
Java语言的物联网
岚溪韵
包罗万象 golang 开发语言 后端
以Java语言的物联网引言物联网(IoT,InternetofThings)是近年来科技发展的一个重要趋势,它连接着各种设备和传感器,通过互联网实现数据的采集、传输和分析,从而为我们的生活和工作带来了便利与高效。随着物联网的发展,编程语言在其中扮演着至关重要的角色。本文将深入探讨Java语言在物联网领域的应用,分析其优势与挑战,并通过实际案例来阐明Java在物联网开发中的实际效果。一、物联网的概念
MongoDB与Cassandra数据库对比
2501_90243449
数据库 mongodb
在深入探讨MongoDB和Cassandra的不同之处之前,让我们先看看它们的相似之处。显然,它们都是数据库。更重要的是,它们都是NoSQL数据库。NoSQL是一种数据库架构类型,其中数据主要以相对非结构化的方式存储。与更传统的SQL式数据库相比,NoSQL可以更有效地存储大量非结构化数据,企业在大数据操作中通常会涉及非结构化数据。MongoDB和Cassandra也都是开源数据库,尽管现在也有商
Android Kotlin Jetpack Compose UI框架 完全解析(1)
2401_84132544
程序员 android kotlin ui
这一功能基于新版AndroidStudio对Compose的支持。新版的AndroidStudioArcticFox(现在还是Canary版本)中添加了许多新工具来支持JetpackCompose新特性,比如:实时文字、动画预览,布局检查等等。1.1.1强大的预览新的AndroidStudio增加了对文字更改实时预览的效果,可以在Preview、模拟器、或者真机上实时预览。1.1.2动画预览可以在
Git通讲-第四章:Git的未来与我的感悟
焦糖酒
Git通讲 git
前言这估计就是本系列的最后一篇文章了,我将在这篇中为系列做个总结,探讨一下git的未来,分享下我洋洋洒洒写了这么多篇文章下来的个人感悟。Git的未来Git不仅是一个强大且灵活的分布式版本控制系统,而且在过去的十几年中不断发展。其未来发展方向体现在两大方面:核心功能的改进和与生态系统中其他工具的整合。Git的持续发展随着技术的发展和用户需求的变化,Git的开发者们不断对其进行优化和扩展。比如,近年来
安装Kubernetes集群-Centos系统
写的花里胡哨
Linux部署 kubernetes centos 容器
文章参考网址:安装Kubernetes集群-K8S教程准备工作一、每个节点分别设置对应主机名hostnamectlset-hostnamemasterhostnamectlset-hostnamenode1hostnamectlset-hostnamenode2二、所有节点都添加hostsvi/etc/hosts172.16.0.4master172.16.32.2node1172.16.32.6
深度学习笔记之自然语言处理(NLP)
电棍233
深度学习 笔记 自然语言处理
深度学习笔记之自然语言处理(NLP)在行将开学之时,我将开始我的深度学习笔记的自然语言处理部分,这部分内容是在前面基础上开展学习的,且目前我的学习更加倾向于通识。自然语言处理部分将包含《动手学深度学习》这本书的第十四章,自然语言处理预训练和第十五章,自然语言处理应用。并且参考原书提供的jupyternotebook资源。自然语言处理,预训练自然语言处理(NaturalLanguageProcess
市场调研数据中台架构:Python 爬虫集群突破反爬限制的工程实践
西攻城狮北
架构 python 爬虫 实战案例
引言在当今数据驱动的商业环境中,市场调研数据对于企业的决策至关重要。为了构建一个高效的数据中台架构,我们需要从多个数据源采集数据,而网络爬虫是获取公开数据的重要手段之一。然而,许多网站为了保护数据,设置了各种反爬机制,如IP封禁、验证码、动态内容加载等。本文将详细介绍如何使用Python爬虫集群突破这些反爬限制,并结合实际工程实践,提供完整的代码示例和优化建议。一、项目背景与需求分析1.市场调研数
什么是pytest.ini及如何在Pytest中应用以提升配置效率
开源优测
pytest
关注开源优测不迷路大数据测试过程、策略及挑战测试框架原理,构建成功的基石在自动化测试工作之前,你应该知道的10条建议在自动化测试中,重要的不是工具当通过控制台运行Pytest测试时你必须记住记录输出、运行时环境变量、设置超时时间、覆盖率、并行执行、依赖项等等。我们擅长的是逻辑思维,而非记忆琐碎事务。这就是我们使用配置文件的原因。它们让你只需指定一次设置,然后就能专注于编写测试。那么,如何在Pyte
达梦数据库针对慢SQL,收集统计信息&清除执行计划缓存
泛冬以南
常用技术记录 数据库 SQL执行计划 统计信息
前言:若遇到以下场景,大概率是SQL走错了执行计划:1、一条SQL在页面上查询特别慢,但拿到数据库终端执行特别快2、一条SQL在某种检索条件下查询特别慢,但拿到数据库终端执行特别快此时,可以尝试按照下述步骤进行恢复:目录一、分析SQL语句中涉及到的物理表,依次收集统计信息1、单表数据量小的表,可通过以下方式收集(针对表中所有字段收集,速度相对慢)2、单表数据量大的表,可通过以下方式收集(针对表中单
力扣LeetCode: 139 单词拆分
不想编程小谭
LeetCode leetcode 算法 动态规划 c++
题目:给你一个字符串s和一个字符串列表wordDict作为字典。如果可以利用字典中出现的一个或多个单词拼接出s则返回true。注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。示例1:输入:s="leetcode",wordDict=["leet","code"]输出:true解释:返回true因为"leetcode"可以由"leet"和"code"拼接成。示例2:输入:s="
cpp智能指针
xianwu543
c++ 开发语言 网络 mysql 数据库
普通指针的不足new和new[]的内存需要用delete和deletel]释放。程序员的主观失误,忘了或漏了释放。程序员也不确定何时释放。普通指针的释放类内的指针,在析构函数中释放。C++内置数据类型,如何释放?new出来的类,本身如何释放?C++11新增三个智能指针类型unique_ptrshared_ptrweak_ptr一、智能指针unique_ptrunique_ptr独享它指向的对象,也
【CCM-SLAM论文阅读笔记】
随机取名字
协同SLAM论文阅读 slam
CCM-SLAM论文阅读笔记整体框架结构如图所示:单智能体只负责采集图像数据,运行实时视觉里程计VO以估计当前位姿和环境地图,由于单智能体计算资源有限,负责生成的局部地图只包含当前N个最近的关键帧。服务器负责地图管理、地点识别、地图融合和全局BA优化。所有局部地图使用本地里程计框架,地图信息在从一个本地里程计到另一个本地里程计框架的相对坐标中进行交换。CCM-SLAM不假设任何关于智能体初始位置的
mac安装jmeter
weixin_41849663
jmeter
前言:最近换了mac,又要安装环境了,记录一下安装过程。一、Jmeter简介ApacheJMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。目前也是测试领域最常用的接口测试和压力测试工具之一。因为JMeter是基于Java开发的,所以使用Jmeter前,需要先安装JDK,然后再安装JMeter。先确认是否有
Oracle SQL Plan Management(SPM)技术原理详解
El Shaddai.plus
oracle数据库的牛逼功能 oracle sql 数据库
OracleSQLPlanManagement(SPM)技术原理详解一、概述:为什么需要SPM?在Oracle数据库中,SQL语句的执行计划(ExecutionPlan)是优化器(CBO)根据统计信息、系统参数和对象结构生成的逻辑操作步骤。然而,以下场景可能导致执行计划不稳定:统计信息更新:表或索引的统计信息变化可能导致优化器选择不同的计划。数据库升级:新版本的优化器算法可能生成更高效(或更低效)
mysql判断索引是否存在 不存在则创建_MySQL存储过程----创建索引前,先判断索引是否已经存在,如果存在,则不添加,如果不存在,添加...
阿尔法查理
mysql判断索引是否存在 不存在则创建
/*一、*安全创建索引的存储过程:*首先判断索引是否存在,如果已经存在则不创建,如果不存在,则创建。*防止索引已经存在,创建出错和删除索引重复创建原来的索引带来的开销浪费**参数说明:*p_dbname:数据库名称*p_tablename:表名称*p_idxname:索引名称*p_index:索引名称和结构,比如在name(name)**举例:比如想要在数据库xxx_db的tablename这张表
25. GD32F103C8T6入门教程-移植FreeRTOS
Car12
GD32 gd32f103 freertos
程序移植的代码:移植方法和stm32一样的哦模板工程建立方法1.在工程下建议FreeRTOS文件夹2.在FreeRTOS文件夹下建立src和port文件夹(src用于存放freertos源码,port文件夹存放内存和接口相关的文件)3.复制freertos/source文件夹下所有c文件复制到刚刚建立的
LeetCode--200. 岛屿数量
Rinai_R
LeetCode leetcode linux 算法 golang 数据结构
200.岛屿数量给你一个由'1'(陆地)和'0'(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。此外,你可以假设该网格的四条边均被水包围。正文创建一个visited二维布尔切片,来判断当前格子走没走过,遍历grid数组,发现’1’,就开始感染,同时岛屿总数+1,此后若再遇见’1’,并且没有被遍历过,说明该陆地没有与之
react19实现在线代码编辑器-codemirror与monaco(并是放置在表单中)
I like Code?
编辑器
本文章提供两个在线代码编辑器实现代码importCodeMirrorfrom'@uiw/react-codemirror'//获取CodeMirror的值,设置为Form的字段值functionhandleCodemirrorEditorChange(value:string|undefined){form.setFieldsValue({fieldC:value||''})//更新form数据}
常用特征检测算法SURF、SIFT、ORB和FAST
super尚
图像处理 算法 人工智能 计算机视觉
特征检测算法SURF算法特征检测的视觉不变性是一个非常重要的概念。但是要解决尺度不变性问题,难度相当大。为解决这一问题,计算机视觉界引入了尺度不变特征的概念。它的理念是,不仅在任何尺度下拍摄的物体都能检测到一致的关键点,而且每个被检测的特征点都对应一个尺度因子。理想情况下,对于两幅图像中不同尺度的的同一个物体点,计算得到的两个尺度因子之间的比率应该等于图像尺度的比率。近几年,人们提出了多种尺度不变
从零开始玩转TensorFlow:小明的机器学习故事 1
山海青风
# 机器学习 机器学习 tensorflow 人工智能
1.引言故事简介小明是一个计算机专业的大三学生,近期在学校里接触到了机器学习。他在某次校园活动中发现,活动主办方总是难以准确预测学生的报名人数,导致准备的物料经常不够或浪费。于是,小明萌生了一个想法:能否通过一些历史数据,用机器学习的方式来预测每场活动的参与率?在老师的建议下,他选择了TensorFlow,一个流行且强大的深度学习框架,希望能将这个想法变成现实。2.开始TensorFlow的旅程场
高级 Java 资源管理:文件和网络优化完整指南
谏君之
java java 网络 开发语言 编程
Java资源管理是构建健壮高效的应用程序的基础。让我们探索有效管理文件和网络资源的高级技术。Java中的资源管理围绕正确处理系统资源(如文件、网络连接和数据库连接)展开。主要目标是确保资源在使用后及时释放,防止内存泄漏和系统资源耗尽。Try-with-resources是处理AutoCloseable资源的最有效模式。下面是一个全面的示例:publicclassResourceHandler{pu
C++模板编程中的类型检查:何时使用类型特性和约束进行提前检查?
泡沫o0
C/C++ 编程世界: 探索C/C++的奥妙 # C++ 泛型编程精选教程 c++ 开发语言 cmake 嵌入式 linux qt c++20
目录标题第一章:引言1.1什么是类型检查?1.1.1类型检查的基本概念1.1.2提前检查与编译器报错的对比1.1.3为什么选择提前检查或者依赖编译器报错?1.2本文目标与结构第二章:C++模板编程中的类型特性和约束2.1什么是类型特性和类型约束?2.1.1类型特性(TypeTraits)类型特性的一个基本示例:2.1.2类型约束(Concepts)类型约束的示例:2.1.3类型特性与类型约束的比较
docker安装kafka和zookeeper
Rain_Rong
运维命令 kafka java-zookeeper docker
下载zookeeperdockerpullwurstmeister/zookeeperdockerpullzookeeper:3.9.1#指定版本有问题启动说内存不够说要升级docker启动zookeeperdockerrun-d--namezookeeper-p2181:2181-twurstmeister/zookeeperdockerrun-d--namezookeeper-p2181:21
LeetCode9. 回文数
坚果-果
LeetCode C++ LeetCode
LeetCode9.回文数题目说明题目说明代码题目说明判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。示例1:输入:121输出:true示例2:输入:-121输出:false解释:从左向右读,为-121。从右向左读,为121-。因此它不是一个回文数。示例3:输入:10输出:false解释:从右向左读,为01。因此它不是一个回文数。进阶:你能不将整数转为字符串
超级详细,知识图谱系统的理论详解+部署过程
mosquito_lover1
python 开发语言 知识图谱
知识图谱系统(KnowledgeGraphSystem)是一种用于表示、存储、查询和推理知识的系统。它通过结构化的方式将现实世界中的实体、概念及其相互关系组织成一个图结构,从而帮助机器理解和处理复杂的知识。知识图谱的核心组成部分实体(Entities):实体是知识图谱中的节点,代表现实世界中的对象或概念。例如,人、地点、组织、事件等。示例:BarackObama、NewYorkCity、Googl
Java 8 Stream API
优知blog
程序员 java 后端
Lambda表达式如何匹配类型接口?=>函数式接口函数式接口是一种只有单一抽象方法的接口,使用@FunctionalInterface来描述,可以隐式地转换成Lambda表达式使用Lambda表达式创建函数式接口的示例,可以让函数成为程序的一等公民,从而像普通数据一样当作参数传递JDK的java.util.function中提供了许多原生的函数式接口,如Supplier@FunctionalInt
大模型产品架构全景解读:从应用场景到技术支持的完整路径
程序员丸子
架构 人工智能 AI大模型 大模型 LLM 大语言模型 RAG
随着人工智能技术的迅猛发展,大模型逐渐成为推动各行业智能化转型的核心动力之一。大模型不仅可以处理大量数据,进行复杂任务的自动化,还能通过微调、蒸馏等技术在特定场景中表现出色。本文将结合大模型产品架构图,详细解读每一个组成模块,帮助读者理解从应用场景到技术支持的完整路径,洞察大模型如何在实际业务中落地。一、落地场景:赋能业务的智能化解决方案大模型的实际价值首先体现在各个业务场景的落地应用中。在架构图
基于Python开发的海关报表自动识别系统的示例代码
go5463158465
python 深度学习 算法 python 开发语言
以下是一个基于Python开发的海关报表自动识别系统的示例代码,该系统包含输入报表、预处理、分类识别、文本检测和生成报表的基本功能。本示例主要使用了pytesseract进行文本识别,opencv-python进行图像预处理,同时简单模拟了报表分类的逻辑。环境准备在运行代码之前,需要安装以下库:pipinstallopencv-pythonpytesseractpandas此外,还需要安装Tess
leetcode9. 回文数(C++)
falldeep
leetcode
题目给你一个整数x,如果x是一个回文整数,返回true;否则,返回false。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121是回文,而123不是。示例1:输入:x=121输出:true示例2:输入:x=-121输出:false解释:从左向右读,为-121。从右向左读,为121-。因此它不是一个回文数。示例3:输入:x=10输出:false解释:从右向左读,为01。因此它
RPC:分布式系统的通信桥梁
r_martian
rpc 网络协议 网络
在当今的软件开发领域,分布式系统已成为处理大规模、高并发业务的主流架构。在分布式系统中,不同服务之间的高效通信至关重要,而远程过程调用(RemoteProcedureCall,简称RPC)技术及其相关框架,正是解决这一通信问题的关键。一、RPC技术概述1.基本概念RPC是一种允许程序调用位于不同地址空间(通常是不同计算机)的过程或函数的技术,就像调用本地函数一样自然和方便。它隐藏了底层网络通信的复
怎么样才能成为专业的程序员?
cocos2d-x小菜
编程 PHP
如何要想成为一名专业的程序员?仅仅会写代码是不够的。从团队合作去解决问题到版本控制,你还得具备其他关键技能的工具包。当我们询问相关的专业开发人员,那些必备的关键技能都是什么的时候,下面是我们了解到的情况。
关于如何学习代码,各种声音很多,然后很多人就被误导为成为专业开发人员懂得一门编程语言就够了?!呵呵,就像其他工作一样,光会一个技能那是远远不够的。如果你想要成为
java web开发 高并发处理
BreakingBad
java Web 并发 开发 处理 高
java处理高并发高负载类网站中数据库的设计方法(java教程,java处理大量数据,java高负载数据) 一:高并发高负载类网站关注点之数据库 没错,首先是数据库,这是大多数应用所面临的首个SPOF。尤其是Web2.0的应用,数据库的响应是首先要解决的。 一般来说MySQL是最常用的,可能最初是一个mysql主机,当数据增加到100万以上,那么,MySQL的效能急剧下降。常用的优化措施是M-S(
mysql批量更新
ekian
mysql
mysql更新优化:
一版的更新的话都是采用update set的方式,但是如果需要批量更新的话,只能for循环的执行更新。或者采用executeBatch的方式,执行更新。无论哪种方式,性能都不见得多好。
三千多条的更新,需要3分多钟。
查询了批量更新的优化,有说replace into的方式,即:
replace into tableName(id,status) values
微软BI(3)
18289753290
微软BI SSIS
1)
Q:该列违反了完整性约束错误;已获得 OLE DB 记录。源:“Microsoft SQL Server Native Client 11.0” Hresult: 0x80004005 说明:“不能将值 NULL 插入列 'FZCHID',表 'JRB_EnterpriseCredit.dbo.QYFZCH';列不允许有 Null 值。INSERT 失败。”。
A:一般这类问题的存在是
Java中的List
g21121
java
List是一个有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
与 set 不同,列表通常允许重复
读书笔记
永夜-极光
读书笔记
1. K是一家加工厂,需要采购原材料,有A,B,C,D 4家供应商,其中A给出的价格最低,性价比最高,那么假如你是这家企业的采购经理,你会如何决策?
传统决策: A:100%订单 B,C,D:0%
&nbs
centos 安装 Codeblocks
随便小屋
codeblocks
1.安装gcc,需要c和c++两部分,默认安装下,CentOS不安装编译器的,在终端输入以下命令即可yum install gccyum install gcc-c++
2.安装gtk2-devel,因为默认已经安装了正式产品需要的支持库,但是没有安装开发所需要的文档.yum install gtk2*
3. 安装wxGTK
yum search w
23种设计模式的形象比喻
aijuans
设计模式
1、ABSTRACT FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory 工厂模式:客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:
开发管理 CheckLists
aoyouzi
开发管理 CheckLists
开发管理 CheckLists(23) -使项目组度过完整的生命周期
开发管理 CheckLists(22) -组织项目资源
开发管理 CheckLists(21) -控制项目的范围开发管理 CheckLists(20) -项目利益相关者责任开发管理 CheckLists(19) -选择合适的团队成员开发管理 CheckLists(18) -敏捷开发 Scrum Master 工作开发管理 C
js实现切换
百合不是茶
JavaScript 栏目切换
js主要功能之一就是实现页面的特效,窗体的切换可以减少页面的大小,被门户网站大量应用思路:
1,先将要显示的设置为display:bisible 否则设为none
2,设置栏目的id ,js获取栏目的id,如果id为Null就设置为显示
3,判断js获取的id名字;再设置是否显示
代码实现:
html代码:
<di
周鸿祎在360新员工入职培训上的讲话
bijian1013
感悟 项目管理 人生 职场
这篇文章也是最近偶尔看到的,考虑到原博客发布者可能将其删除等原因,也更方便个人查找,特将原文拷贝再发布的。“学东西是为自己的,不要整天以混的姿态来跟公司博弈,就算是混,我觉得你要是能在混的时间里,收获一些别的有利于人生发展的东西,也是不错的,看你怎么把握了”,看了之后,对这句话记忆犹新。 &
前端Web开发的页面效果
Bill_chen
html Web Microsoft
1.IE6下png图片的透明显示:
<img src="图片地址" border="0" style="Filter.Alpha(Opacity)=数值(100),style=数值(3)"/>
或在<head></head>间加一段JS代码让透明png图片正常显示。
2.<li>标
【JVM五】老年代垃圾回收:并发标记清理GC(CMS GC)
bit1129
垃圾回收
CMS概述
并发标记清理垃圾回收(Concurrent Mark and Sweep GC)算法的主要目标是在GC过程中,减少暂停用户线程的次数以及在不得不暂停用户线程的请夸功能,尽可能短的暂停用户线程的时间。这对于交互式应用,比如web应用来说,是非常重要的。
CMS垃圾回收针对新生代和老年代采用不同的策略。相比同吞吐量垃圾回收,它要复杂的多。吞吐量垃圾回收在执
Struts2技术总结
白糖_
struts2
必备jar文件
早在struts2.0.*的时候,struts2的必备jar包需要如下几个:
commons-logging-*.jar Apache旗下commons项目的log日志包
freemarker-*.jar
Jquery easyui layout应用注意事项
bozch
jquery 浏览器 easyui layout
在jquery easyui中提供了easyui-layout布局,他的布局比较局限,类似java中GUI的border布局。下面对其使用注意事项作简要介绍:
如果在现有的工程中前台界面均应用了jquery easyui,那么在布局的时候最好应用jquery eaysui的layout布局,否则在表单页面(编辑、查看、添加等等)在不同的浏览器会出
java-拷贝特殊链表:有一个特殊的链表,其中每个节点不但有指向下一个节点的指针pNext,还有一个指向链表中任意节点的指针pRand,如何拷贝这个特殊链表?
bylijinnan
java
public class CopySpecialLinkedList {
/**
* 题目:有一个特殊的链表,其中每个节点不但有指向下一个节点的指针pNext,还有一个指向链表中任意节点的指针pRand,如何拷贝这个特殊链表?
拷贝pNext指针非常容易,所以题目的难点是如何拷贝pRand指针。
假设原来链表为A1 -> A2 ->... -> An,新拷贝
color
Chen.H
JavaScript html css
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML> <HEAD>&nbs
[信息与战争]移动通讯与网络
comsci
网络
两个坚持:手机的电池必须可以取下来
光纤不能够入户,只能够到楼宇
建议大家找这本书看看:<&
oracle flashback query(闪回查询)
daizj
oracle flashback query flashback table
在Oracle 10g中,Flash back家族分为以下成员:
Flashback Database
Flashback Drop
Flashback Table
Flashback Query(分Flashback Query,Flashback Version Query,Flashback Transaction Query)
下面介绍一下Flashback Drop 和Flas
zeus持久层DAO单元测试
deng520159
单元测试
zeus代码测试正紧张进行中,但由于工作比较忙,但速度比较慢.现在已经完成读写分离单元测试了,现在把几种情况单元测试的例子发出来,希望有人能进出意见,让它走下去.
本文是zeus的dao单元测试:
1.单元测试直接上代码
package com.dengliang.zeus.webdemo.test;
import org.junit.Test;
import o
C语言学习三printf函数和scanf函数学习
dcj3sjt126com
c printf scanf language
printf函数
/*
2013年3月10日20:42:32
地点:北京潘家园
功能:
目的:
测试%x %X %#x %#X的用法
*/
# include <stdio.h>
int main(void)
{
printf("哈哈!\n"); // \n表示换行
int i = 10;
printf
那你为什么小时候不好好读书?
dcj3sjt126com
life
dady, 我今天捡到了十块钱, 不过我还给那个人了
good girl! 那个人有没有和你讲thank you啊
没有啦....他拉我的耳朵我才把钱还给他的, 他哪里会和我讲thank you
爸爸, 如果地上有一张5块一张10块你拿哪一张呢....
当然是拿十块的咯...
爸爸你很笨的, 你不会两张都拿
爸爸为什么上个月那个人来跟你讨钱, 你告诉他没
iptables开放端口
Fanyucai
linux iptables 端口
1,找到配置文件
vi /etc/sysconfig/iptables
2,添加端口开放,增加一行,开放18081端口
-A INPUT -m state --state NEW -m tcp -p tcp --dport 18081 -j ACCEPT
3,保存
ESC
:wq!
4,重启服务
service iptables
Ehcache(05)——缓存的查询
234390216
排序 ehcache 统计 query
缓存的查询
目录
1. 使Cache可查询
1.1 基于Xml配置
1.2 基于代码的配置
2 指定可搜索的属性
2.1 可查询属性类型
2.2 &
通过hashset找到数组中重复的元素
jackyrong
hashset
如何在hashset中快速找到重复的元素呢?方法很多,下面是其中一个办法:
int[] array = {1,1,2,3,4,5,6,7,8,8};
Set<Integer> set = new HashSet<Integer>();
for(int i = 0
使用ajax和window.history.pushState无刷新改变页面内容和地址栏URL
lanrikey
history
后退时关闭当前页面
<script type="text/javascript">
jQuery(document).ready(function ($) {
if (window.history && window.history.pushState) {
应用程序的通信成本
netkiller.github.com
虚拟机 应用服务器 陈景峰 netkiller neo
应用程序的通信成本
什么是通信
一个程序中两个以上功能相互传递信号或数据叫做通信。
什么是成本
这是是指时间成本与空间成本。 时间就是传递数据所花费的时间。空间是指传递过程耗费容量大小。
都有哪些通信方式
全局变量
线程间通信
共享内存
共享文件
管道
Socket
硬件(串口,USB) 等等
全局变量
全局变量是成本最低通信方法,通过设置
一维数组与二维数组的声明与定义
恋洁e生
二维数组 一维数组 定义 声明 初始化
/** * */ package test20111005; /** * @author FlyingFire * @date:2011-11-18 上午04:33:36 * @author :代码整理 * @introduce :一维数组与二维数组的初始化 *summary: */ public c
Spring Mybatis独立事务配置
toknowme
mybatis
在项目中有很多地方会使用到独立事务,下面以获取主键为例
(1)修改配置文件spring-mybatis.xml <!-- 开启事务支持 --> <tx:annotation-driven transaction-manager="transactionManager" /> &n
更新Anadroid SDK Tooks之后,Eclipse提示No update were found
xp9802
eclipse
使用Android SDK Manager 更新了Anadroid SDK Tooks 之后,
打开eclipse提示 This Android SDK requires Android Developer Toolkit version 23.0.0 or above, 点击Check for Updates
检测一会后提示 No update were found