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

python 爬虫 做网站怎么利用互联网推广

python 爬虫 做网站,怎么利用互联网推广,桂林旅游网页设计,wordpress注册函数该项目的前篇内容的使用jwt令牌实现登录认证,使用Md5加密实现注册,在上一篇:http://t.csdnimg.cn/vn3rB 该篇主要内容:redis优化登录和ThreadLocal提供线程局部变量,以及该大新闻项目的主要代码。 redis优化登录 其实…

该项目的前篇内容的使用jwt令牌实现登录认证,使用Md5加密实现注册,在上一篇:http://t.csdnimg.cn/vn3rB

该篇主要内容:redis优化登录和ThreadLocal提供线程局部变量,以及该大新闻项目的主要代码。

redis优化登录

其实在前面项目中的登录,有一个令牌机制的bug,就是在你修改密码后,原来密码的登录进去的token,还是可以使用的,旧令牌并没有失效,这会造成用户在修改密码后,但是原来密码登录进去的页面仍然可以正常访问,有很大的安全隐患。

所以使用redis来解决这个问题

令牌主动失效机制

  • 登录成功后,给浏览器响应令牌的同时,把该令牌存储到 redis 中
  • LoginInterceptor 拦截器中,需要验证浏览器携带的令牌,并同时需要获取到 redis 中存储的与之相同的令牌
  • 当用户修改密码成功后,删除 redis 中存储的旧令牌

redis的测试代码:

package com.xu;import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;import java.util.concurrent.TimeUnit;@SpringBootTest //如果在测试类上添加了这个注释,那么将来单元测试方法执行之前,会先初始化Spring容器
public class RedisTest {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testpublic void testSet(){//让redis中存储一个键值对 StringRedisTemplateValueOperations<String, String> operations = stringRedisTemplate.opsForValue();operations.set("username","zhangsan");operations.set("id","1",15, TimeUnit.SECONDS);}@Testpublic void testGet(){ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();System.out.println(operations.get("username"));}
}

运行效果:

其实里面的id是设置了失效的时间,所以在超出时间的范围外,则get不到id的值。

在整个项目的代码中,redis的使用也是类似:

UserController部分代码:

@Autowired
private UserService userService;
@Autowired
private StringRedisTemplate stringRedisTemplate;@PostMapping("login")public Result<String> login(@Pattern(regexp = "^\\S{5,16}$")String username, @Pattern(regexp = "^\\S{5,16}$")String password){//根据用户名查询用户User loginUser=userService.findByUserName(username);//判断用户是否存在if(loginUser==null){return Result.error("用户名错误");}//判断密码是否正确if(Md5Util.getMD5String(password).equals(loginUser.getPassword())){//登录成功Map<String,Object> claims=new HashMap<>();claims.put("id",loginUser.getId());claims.put("username",loginUser.getUsername());String token= JwtUtil.genToken(claims);//把token存储到redis里面ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();operations.set(token,token,1, TimeUnit.HOURS);return Result.success(token);}return Result.error("密码错误");}@PatchMapping("updatePwd")public Result updatePwd(@RequestBody Map<String,String> params,@RequestHeader("Authorization") String token){//校验参数String oldPwd = params.get("old_pwd");String newPwd = params.get("new_pwd");String rePwd = params.get("re_pwd");if(!StringUtils.hasLength(oldPwd) || !StringUtils.hasLength(newPwd) || !StringUtils.hasLength(rePwd)){return Result.error("缺失必要的参数");}//原密码是否正确//调用userService根据用户名拿到原密码,再和old_pwd比对Map<String,Object> map=ThreadLocalUtil.get();String username=(String) map.get("username");User loginUser=userService.findByUserName(username);if(!loginUser.getPassword().equals(Md5Util.getMD5String(oldPwd))){return Result.error("原密码填写不正确");}//newPwd和rePwd是否一样if(!rePwd.equals(newPwd)){return Result.error("两次填写的新密码不一样");}//调用service完成密码更新userService.updatePwd(newPwd);//删除redis中对应的tokenValueOperations<String, String> operations = stringRedisTemplate.opsForValue();operations.getOperations().delete(token);return Result.success();}

LoginInterceptor代码:

package com.xu.interceptors;import com.xu.pojo.Result;
import com.xu.utils.JwtUtil;
import com.xu.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import java.util.Map;@Component
public class LoginInterceptor implements HandlerInterceptor {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//令牌验证String token=request.getHeader("Authorization");//验证tokentry {//从redis中获取相同的tokenValueOperations<String, String> operations = stringRedisTemplate.opsForValue();String redisToken = operations.get(token);if(redisToken==null){//token已经失效throw new RuntimeException();}Map<String,Object> claims= JwtUtil.parseToken(token);//把业务数据存储到ThreadLocal中ThreadLocalUtil.set(claims);//放行return true;}catch (Exception e){response.setStatus(401);//不放行return false;}}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {//清空ThreadLocal中的数据ThreadLocalUtil.remove();}
}

ThreadLocal

适用场景ThreadLocal 适用于每个线程需要独立的实例或数据的场景,不适用于需要线程间共享数据的场景。

  • 用来存取数据 : set()/get()
  • 使用 ThreadLocal 存储的数据 , 线程安全
  • 用完记得调用 remove 方法释放

而在本项目中文章分类和文章管理都是通过用户去操作的,所以适合用ThreadLocal 存储数据。

测试代码:

package com.xu;import org.junit.jupiter.api.Test;public class ThreadLocalSetAndGet {@Testpublic void testThreadLocalSetAndGet(){//提供一个ThreadLocal对象ThreadLocal tl=new ThreadLocal();//开启两个线程new Thread(()->{tl.set("cookie");System.out.println(Thread.currentThread().getName()+":"+tl.get());System.out.println(Thread.currentThread().getName()+":"+tl.get());System.out.println(Thread.currentThread().getName()+":"+tl.get());},"pig").start();new Thread(()->{tl.set("offer");System.out.println(Thread.currentThread().getName()+":"+tl.get());System.out.println(Thread.currentThread().getName()+":"+tl.get());System.out.println(Thread.currentThread().getName()+":"+tl.get());},"lucky").start();}
}

运行结果:

ThreadLocalUtil代码:

package com.xu.utils;import java.util.HashMap;
import java.util.Map;/*** ThreadLocal 工具类*/
@SuppressWarnings("all")
public class ThreadLocalUtil {//提供ThreadLocal对象,private static final ThreadLocal THREAD_LOCAL = new ThreadLocal();//根据键获取值public static <T> T get(){return (T) THREAD_LOCAL.get();}//存储键值对public static void set(Object value){THREAD_LOCAL.set(value);}//清除ThreadLocal 防止内存泄漏public static void remove(){THREAD_LOCAL.remove();}
}

ArticleServiceImpl部分使用到了ThreadLocal的代码:

package com.xu.service.impl;import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xu.mapper.ArticleMapper;
import com.xu.pojo.Article;
import com.xu.pojo.PageBean;
import com.xu.service.ArticleService;
import com.xu.utils.ThreadLocalUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;@Service
public class ArticleServiceImpl implements ArticleService {@Autowiredprivate ArticleMapper articleMapper;@Overridepublic void add(Article article) {//补充属性值article.setCreateTime(LocalDateTime.now());article.setUpdateTime(LocalDateTime.now());Map<String,Object> map= ThreadLocalUtil.get();Integer userId=(Integer) map.get("id");article.setCreateUser(userId);articleMapper.add(article);}@Overridepublic PageBean<Article> list(Integer pageNum, Integer pageSize, Integer categoryId, String state) {//创建PageBean对象PageBean<Article> pb=new PageBean<>();//开启分页查询 PageHelperPageHelper.startPage(pageNum,pageSize);//调用mapperMap<String,Object> map=ThreadLocalUtil.get();Integer userId=(Integer)map.get("id");List<Article> as= articleMapper.list(userId,categoryId,state);Page<Article> p=(Page<Article>) as;//把数据填充到PageBean对象pb.setTotal(p.getTotal());pb.setItems(p.getResult());return pb;}
}

分组校验

把校验项进行归类分组,在完成不同的功能的时候,校验指定组中的校验项

  • 1. 定义分组
  • 2. 定义校验项时指定归属的分组
  • 3. 校验时指定要校验的分组

1. 如何定义分组?

在实体类内部定义接口
2. 如何对校验项分组?

通过 groups 属性指定
3. 校验时如何指定分组?

给 @Validated 注解的 value 属性赋值
4. 校验项默认属于什么组 ?

Default

在本项目中,category里面的新增和更新方法,需要携带的校验参数是不一样,比如:新增的id是自增的,更新的id是要修改category对应的id(那么更新就必须携带id参数),所以在实体类category里面可以使用groups进行分组

category代码:

package com.xu.pojo;import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.groups.Default;
import lombok.Data;import java.time.LocalDateTime;
@Data
public class Category {@NotNull(groups = Update.class)private Integer id;//主键ID@NotEmptyprivate String categoryName;//分类名称@NotEmptyprivate String categoryAlias;//分类别名private Integer createUser;//创建人ID@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime createTime;//创建时间@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime updateTime;//更新时间//如果说某个校验项没有指定分组,默认属于Default分组//分组之间可以继承, A extends B  那么A中拥有B中所有的校验项public interface Add extends Default {}public interface Update extends Default {}
}

CategoryController部分方法代码:

package com.xu.controller;import com.xu.pojo.Category;
import com.xu.pojo.Result;
import com.xu.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
@RequestMapping("/category")
public class CategoryController {@Autowiredprivate CategoryService categoryService;@PostMappingpublic Result add(@RequestBody @Validated(Category.Add.class) Category category){categoryService.add(category);return Result.success();}@PutMappingpublic Result update(@RequestBody @Validated(Category.Update.class) Category category) {categoryService.update(category);return Result.success();}
}

使用上面这些,需要在pom.xml里面添加:


<!--      validation依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency><!--      redis坐标--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

大新闻项目的重要业务有文件上传,分页查询以及文章管理(增删改查)等,

以下是一些难点的业务:

文件上传:

文件上传里面使用了UUID是为了防止相同文件名的,被覆盖,所以就使用UUID生成随机的文件名

分页查询:

ArticleController部分代码:

    @GetMappingpublic Result<PageBean<Article>> list(Integer pageNum,Integer pageSize,@RequestParam(required = false) Integer categoryId,@RequestParam(required = false) String state){PageBean<Article> pb=articleService.list(pageNum,pageSize,categoryId,state);return Result.success(pb);}

ArticleServiceImpl的代码:

package com.xu.service.impl;import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xu.mapper.ArticleMapper;
import com.xu.pojo.Article;
import com.xu.pojo.PageBean;
import com.xu.service.ArticleService;
import com.xu.utils.ThreadLocalUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;@Service
public class ArticleServiceImpl implements ArticleService {@Autowiredprivate ArticleMapper articleMapper;@Overridepublic void add(Article article) {//补充属性值article.setCreateTime(LocalDateTime.now());article.setUpdateTime(LocalDateTime.now());Map<String,Object> map= ThreadLocalUtil.get();Integer userId=(Integer) map.get("id");article.setCreateUser(userId);articleMapper.add(article);}@Overridepublic PageBean<Article> list(Integer pageNum, Integer pageSize, Integer categoryId, String state) {//创建PageBean对象PageBean<Article> pb=new PageBean<>();//开启分页查询 PageHelperPageHelper.startPage(pageNum,pageSize);//调用mapperMap<String,Object> map=ThreadLocalUtil.get();Integer userId=(Integer)map.get("id");List<Article> as= articleMapper.list(userId,categoryId,state);Page<Article> p=(Page<Article>) as;//把数据填充到PageBean对象pb.setTotal(p.getTotal());pb.setItems(p.getResult());return pb;}
}

ArticleMapper代码:

package com.xu.mapper;import com.xu.pojo.Article;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;import java.util.List;@Mapper
public interface ArticleMapper {//新增@Insert("insert into article(title,content,cover_img,state,category_id,create_user,create_time,update_time) "+"values(#{title},#{content},#{coverImg},#{state},#{categoryId},#{createUser},#{createTime},#{updateTime})")void add(Article article);List<Article> list(Integer userId, Integer categoryId, String state);
}

这里使用到了动态sql,要保证在resource目录下的路径映射和mapper的一样:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xu.mapper.ArticleMapper">
<!--    动态sql--><select id="list" resultType="com.xu.pojo.Article">select * from article<where><if test="categoryId!=null">category_id=#{categoryId}</if><if test="state!=null">and state=#{state}</if>and create_user=#{userId}</where></select>
</mapper>


文章转载自:
http://dinncodireful.ssfq.cn
http://dinnconeonatology.ssfq.cn
http://dinncolandsraad.ssfq.cn
http://dinncoannihilation.ssfq.cn
http://dinncobirth.ssfq.cn
http://dinncopaedomorphism.ssfq.cn
http://dinncodisintermediate.ssfq.cn
http://dinncoknobbly.ssfq.cn
http://dinncofreightage.ssfq.cn
http://dinncomatsudo.ssfq.cn
http://dinncodigest.ssfq.cn
http://dinncocounterattraction.ssfq.cn
http://dinncocompilatory.ssfq.cn
http://dinncopulpiness.ssfq.cn
http://dinncofrostiness.ssfq.cn
http://dinncoachievable.ssfq.cn
http://dinncobranchiae.ssfq.cn
http://dinncoglazy.ssfq.cn
http://dinncounhandsome.ssfq.cn
http://dinncoconferral.ssfq.cn
http://dinncostack.ssfq.cn
http://dinncoforehanded.ssfq.cn
http://dinncomigraineur.ssfq.cn
http://dinncooleomargarin.ssfq.cn
http://dinncoleatherjacket.ssfq.cn
http://dinncogill.ssfq.cn
http://dinncoabortionism.ssfq.cn
http://dinncosympathomimetic.ssfq.cn
http://dinncofirethorn.ssfq.cn
http://dinncoserogroup.ssfq.cn
http://dinncoilly.ssfq.cn
http://dinncocharger.ssfq.cn
http://dinncocrackling.ssfq.cn
http://dinncoacademically.ssfq.cn
http://dinncoflintshire.ssfq.cn
http://dinncopetrological.ssfq.cn
http://dinncoavow.ssfq.cn
http://dinncovole.ssfq.cn
http://dinncoslobbery.ssfq.cn
http://dinncohungerly.ssfq.cn
http://dinncohoopla.ssfq.cn
http://dinncoassentation.ssfq.cn
http://dinncodioptric.ssfq.cn
http://dinncoparamountcy.ssfq.cn
http://dinncoaltaic.ssfq.cn
http://dinncoinvincible.ssfq.cn
http://dinnconlc.ssfq.cn
http://dinncogyrodyne.ssfq.cn
http://dinncosusceptive.ssfq.cn
http://dinncooctonal.ssfq.cn
http://dinncoabsorptiometer.ssfq.cn
http://dinnconominee.ssfq.cn
http://dinncosardis.ssfq.cn
http://dinncoguggenheim.ssfq.cn
http://dinncosupernaculum.ssfq.cn
http://dinncoectogenic.ssfq.cn
http://dinncocornetist.ssfq.cn
http://dinncoarcturus.ssfq.cn
http://dinncohorsefoot.ssfq.cn
http://dinncodiagrammatize.ssfq.cn
http://dinncofuliginous.ssfq.cn
http://dinncofilmnoir.ssfq.cn
http://dinncodeserter.ssfq.cn
http://dinncogaius.ssfq.cn
http://dinncofogey.ssfq.cn
http://dinncogirondist.ssfq.cn
http://dinncosaleslady.ssfq.cn
http://dinncoclubhaul.ssfq.cn
http://dinncocomatula.ssfq.cn
http://dinncocateyed.ssfq.cn
http://dinncocogon.ssfq.cn
http://dinncohydrocoral.ssfq.cn
http://dinncoaccidental.ssfq.cn
http://dinncocanonist.ssfq.cn
http://dinncophosphoroscope.ssfq.cn
http://dinncounwind.ssfq.cn
http://dinncoointment.ssfq.cn
http://dinncodaddle.ssfq.cn
http://dinncounderthrust.ssfq.cn
http://dinncomooring.ssfq.cn
http://dinncoastonished.ssfq.cn
http://dinncounpersuasive.ssfq.cn
http://dinncodwc.ssfq.cn
http://dinncocolourbreed.ssfq.cn
http://dinncointerfoliar.ssfq.cn
http://dinncokegler.ssfq.cn
http://dinncobilliardist.ssfq.cn
http://dinncojoanne.ssfq.cn
http://dinncoestuary.ssfq.cn
http://dinncoaquiform.ssfq.cn
http://dinncocrookery.ssfq.cn
http://dinncopredictability.ssfq.cn
http://dinncoperpend.ssfq.cn
http://dinncofreebsd.ssfq.cn
http://dinncopamirs.ssfq.cn
http://dinncodecagonal.ssfq.cn
http://dinncopoll.ssfq.cn
http://dinncosainfoin.ssfq.cn
http://dinncohurtlingly.ssfq.cn
http://dinncocablecasting.ssfq.cn
http://www.dinnco.com/news/154678.html

相关文章:

  • 手机版网站嵌入代码企业类网站有哪些例子
  • 怎样做动态网站模板建站平台
  • 做网站的要求seo定义
  • wordpress 导航标签长春百度seo公司
  • 上海网站营销是什么搜狗站长平台打不开
  • 内部网站建设教程b站推广渠道
  • 网站开发网站设计网站制作400哪家好
  • wordpress 评论提醒邮件插件搜索引擎优化的各种方法
  • 鲅鱼圈网站建设苏州seo网站系统
  • 广州最新疫情公布苏州seo关键词优化外包
  • 上海 网站公司廊坊seo整站优化软件
  • 南通做网站baidu tg广州广告公司
  • 公安免费网站模板足球比赛今日最新推荐
  • 网站备案做网站要转移吗常用的搜索引擎有哪些
  • 毕业设计做网站还是系统百度应用平台
  • 手机企业网站源码页面关键词优化
  • 长春网站制作wang优化设计六年级下册数学答案
  • 亿万网站打开百度搜索
  • 长沙专业网站建设公司排名百度小程序对网站seo
  • javascript和java济南专业seo推广公司
  • 天津综合网站建设商店网络服务提供者不是网络运营者
  • 如何做向日葵官方网站搜索引擎营销的步骤
  • 江门市住房和城乡建设局门户网站济南做seo排名
  • 免备案域名是危险网站seo推广费用
  • 变化型网站今日头条热搜
  • 郑州web网站制作广东深圳龙华区
  • app手机网站设计360搜索引擎入口
  • 做热处理工艺的网站有哪些网站测试报告
  • c 网站开发模板产品seo怎么优化
  • magento做预订类网站seo优化关键词是什么意思