【开源项目--稻草】Day04

【开源项目--稻草】Day04

  • 1. 续 VUE
    • 1.1 完善VUE+AJAX完成注册功能
  • Spring验证框架
    • 什么是Spring验证框架
    • 使用Spring-Validation
  • 稻草问答-学生首页
    • 显示首页
    • 制作首页的流程
    • 开发标签列表
      • 标签列表显示原理
    • 从业务逻辑层开始
    • 编写控制层代码
    • 开发问题列表
      • 开发业务逻辑层
      • 开发页面和JS代码显示问题
  • 随笔

1. 续 VUE

1.1 完善VUE+AJAX完成注册功能

我们现在注册用户只能在浏览器控制台看到结果

怎么能再注册页面上看到注册结果呢?

实际上,register.html页面已经准备好了一个显示注册信息的div

改写它代码如下

<div id="error" class="alert alert-danger"style="display: none"v-bind:class="{'d-block':hasError}"><i class="fa fa-exclamation-triangle"></i><span v-text="message">邀请码错误!</span>
</div>

其中v-bind:class="{‘d-block’:hasError}"的含义为

根据Vue代码中绑定的hasError变量来决定是否将class="d-block"加入到当前div中

如果将这个class加入得到当前div的样式中,则这个div会显示出来

页面修改后,register.js文件也要随之修改

代码如下

let app = new Vue({el:'#app',data:{inviteCode:'',phone:'',nickname:'',password:'',confirm:'',message:'',hasError:false},methods:{register:function () {console.log('Submit');let data = {inviteCode: this.inviteCode,phone: this.phone,nickname: this.nickname,password: this.password,confirm: this.confirm}console.log(data);if(data.password !== data.confirm){this.message="两次密码输入不一致";this.hasError=true;return;}$.ajax({url:"/register",method: "POST",data: data,success: function (r) {console.log(r);if(r.code == CREATED){console.log("注册成功");console.log(r.message);//注册成功,可以直接跳转到登录页location.href="/login.html?register";}else{console.log(r.message);//如果注册失败将信息显示在信息Div中app.message=r.message;app.hasError=true;}}});}}
});

新增两个属性:hasError和message

这两个属性控制页面上是否显示错误div以及错误div中出现的提示信息是什么

Spring验证框架

什么是Spring验证框架

Spring提供的对用户输入信息进行验证的框架组件

是服务器端验证技术

在这里插入图片描述

使用Spring验证框架验证发送到服务器的内容的合法性!

Spring-validation(验证)

使用Spring-Validation

步骤1:

导入依赖

子项目pom.xml文件添加:

<!-- 验证框架 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>

步骤2:

定位到要验证信息的实体类

将验证规则按照给定注解来标记即可

要验证注册业务,就找RegisterVo类即可

@Data
public class RegisterVo implements Serializable {//只能作用在String上,不能为null,去掉空格之后也不能为""@NotBlank(message = "邀请码不能为空")private String inviteCode;@NotBlank(message = "用户名不能为空")//@Pattern()表示下面的属性需要通过指定正则表达式的判断@Pattern(regexp="^1\\d{10}$",message ="手机号格式不正确")private String phone;@NotBlank(message = "昵称不能为空")@Pattern(regexp="^.{2,20}$",message ="昵称在2到20位之间")private String nickname;@NotBlank(message = "密码不能为空")@Pattern(regexp="^\\w{6,20}$",message ="密码在6~20位之间")private String password;@NotBlank(message = "确认密码不能为空")private String confirm;}

步骤3:

在控制器从表单或ajax获得实体类对象参数时就可以对这个实体类属性的值进行上面设置的验证了

验证方法非常简单,只需要加一个注解即可!

SystemController注册方法代码修改如下

@PostMapping("/register")public R registerStudent(//控制器接收的参数前加@Validated//表示要按这个类规定的验证规则,验证这个对象属性的值@Validated RegisterVo registerVo,//固定用法,在验证参数后再跟一个参数:BindingResult//这个参数中记录保存上面验证过程中的验证信息和结果BindingResult validaResult){//在控制器调用业务逻辑前,先判断BindingResult对象中是否有错误if(validaResult.hasErrors()){//如果验证结果中包含任何错误信息,进入这个if//获得其中的一个错误信息显示,一般是按顺序的第一个错误信息String error=validaResult.getFieldError().getDefaultMessage();return R.unproecsableEntity(error);}System.out.println(registerVo);log.debug("得到信息为:{}",registerVo);try{userService.registerStudent(registerVo);return R.created("注册成功!");}catch (ServiceException e){log.error("注册失败",e);return R.failed(e);}}

就可以测试验证的效果了

稻草问答-学生首页

显示首页

步骤1:

将static文件中的index.html复制到templates文件夹中

步骤2:

创建HomeController类,显示index.html

代码如下

@RestController
@Slf4j
public class HomeController {//显示首页@GetMapping("/index.html")public ModelAndView index(){return  new ModelAndView("index");}
}

步骤3:

撤销在SecurityConfig类中对index.html的放行

达到必须登录才能访问主页的效果

http.csrf().disable().authorizeRequests()//对当前全部请求进行授权.antMatchers("/img/*","/js/*","/css/*","/bower_components/**","/login.html","/register.html","/register")//设置路径.permitAll()//允许全部请求访问上面定义的路径//其它路径需要全部进行表单登录验证.anyRequest().authenticated().and().formLogin().loginPage("/login.html").loginProcessingUrl("/login").failureUrl("/login.html?error").defaultSuccessUrl("/index.html").and().logout().logoutUrl("/logout").logoutSuccessUrl("/login.html?logout");

制作首页的流程

1.制作首页导航栏的tag列表

2.制作学生问题的显示和分页

3.制作学生信息面板

开发标签列表

标签列表显示原理

在这里插入图片描述

在用户已经能够登录显示主页的前提下

  1. 主页页面中编写ajax向控制器发送请求所有标签
  2. 控制接到请求后调用业务逻辑层
  3. 业务逻辑层从tagMapper接口查询所有标签
  4. 业务逻辑层将查询到的信息返回给控制器
  5. 控制器获得所以标签返回JSON格式
  6. ajax中获得JSON对象,利用VUE绑定显示在页面上

从业务逻辑层开始

我们可以选择先编写业务逻辑层

步骤1:

ITagService接口中添加方法

public interface ITagService extends IService<Tag> {List<Tag> getTags();
}

步骤2:

实现这个接口

TagServiceImpl类中代码如下

@Service
public class TagServiceImpl extends ServiceImpl<TagMapper, Tag> implements ITagService {//CopyOnWriteArrayList<>是线程安全的集合,适合在高并发的环境下使用private final List<Tag> tags=new CopyOnWriteArrayList<>();@Overridepublic List<Tag> getTags() {//这个if主要是为了保证tags被顺利赋值之后的高效运行if(tags.isEmpty()) {synchronized (tags) {//这个if主要是为了保证不会有两条以上线程为tags重复添加内容if (tags.isEmpty()) {//super.list()是父类提供的查询当前指定实体类全部行的代码tags.addAll(super.list());}}}return tags;}
}

步骤3:

测试

@SpringBootTest
public class TagTest {@AutowiredITagService tagService;@Testpublic void test() {List<Tag> list = tagService.getTags();for (Tag tag : list)System.out.println(tag);}}

编写控制层代码

步骤1:

TagController类中编写代码如下

@RestController
//下面的注解表示想访问本控制器中的任何方法需要前缀/v1/tags
//这个v1开头的格式是后期微服务的标准名为RESTful
@RequestMapping("/v1/tags")
public class TagController {@Autowiredprivate ITagService tagService;//查询所有标签@GetMapping("")表示使用类上声明的前缀就可以访问这个方法@GetMapping("")public R<List<Tag>> tags(){List<Tag> list=tagService.getTags();return R.ok(list);}
}

步骤2:

到页面中(index.html)绑定vue需要的变量

页面代码如下

	<div class="nav font-weight-light" id="tagsApp"><a href="tag/tag_question.html" class="nav-item nav-link text-info">	<small>全部</small></a><!-- v-for 循环中in左侧是随意起的变量名,会在循环体中使用in右侧的变量名,绑定这VUE代码中的变量--><a href="tag/tag_question.html"class="nav-item nav-link text-info"v-for="tag in tags"><small v-text="tag.name">Java基础</small></a></div>

步骤3:

index.html网页的结束位置要引入两个js文件

</body>
<script src="js/utils.js"></script>
<script src="js/index.js"></script>
<script src="js/tags_nav.js"></script>
</html>

步骤4:

编写js/tags_nav.js代码如下

let tagsApp = new Vue({el:'#tagsApp',data:{tags:[]},methods:{loadTags:function () {console.log('执行了 loadTags');$.ajax({url:'/v1/tags',method:'GET',success:function (r) {console.log(r);if (r.code === OK){console.log('成功获取tags');//将从控制器获得的所有标签赋值给vue定义的//tags数组,由于双向绑定,赋值同时页面就开始循环了tagsApp.tags = r.data;}}});}},//这个方法会在页面加载完毕之后运行created:function () {//页面加载完毕,立即调用loadTagsthis.loadTags();}
});

开发问题列表

了解开发流程

在这里插入图片描述

开发业务逻辑层

步骤1:

在业务逻辑层的接口中声明方法

IQuestionService接口给中声明方法

public interface IQuestionService extends IService<Question> {//按登录用户查询当前用户问题的方法List<Question> getMyQuestions();
}

步骤2:

要想实现查询当前登录的用户信息,必须使用Spring-Security提供的指定方法

调用这个方法的代码可能在项目后面的业务中也需要

这样写字QuestionService中就不合适了,所以我们先在IUserService中添加一个获得当前登录用户名的方法

IUserService添加代码

 //从Spring-Security中获得当前登录用户的用户名的方法String currentUsername();

步骤3:

在UserServiceImpl类中实现获得当前登录用户名并返回

@Overridepublic String currentUsername() {//利用Spring-Security框架获得当前登录用户信息Authentication authentication=SecurityContextHolder.getContext().getAuthentication();//判断当前用户有没有登录,如果没有登录抛出异常if(!(authentication instanceof AnonymousAuthenticationToken)){//上面代码是判断当前用的抽象权限类型是不是匿名用户//如果不是匿名用户,就是登录的用户,只有登录的用户才能返回用户名String username=authentication.getName();return username;}//没运行上面的if证明用户没有登录,抛出异常即可throw ServiceException.notFound("没有登录");}

步骤4:

现在就可以在QuestionServiceImpl类中调用上面编写的方法来获得当前登录用户了

在根据这个用户信息(id)查询这个用户的问题

代码如下

@Service
@Slf4j
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements IQuestionService {@AutowiredIUserService userService;@AutowiredUserMapper userMapper;@AutowiredQuestionMapper questionMapper;//按登录用户查询当前用户问题的方法@Overridepublic List<Question> getMyQuestions() {//获得当前登录用户的用户名String username=userService.currentUsername();log.debug("当前登录用户为:{}",username);//如果已经登录,使用之前编写好的findUserByUsername方法//查询出当前用户的详细信息(实际上主要需要用户的id)User user=userMapper.findUserByUsername(username);if(user == null){throw ServiceException.gone("登录用户不存在");}log.debug("开始查询{}用户的问题",user.getId());QueryWrapper<Question> queryWrapper=new QueryWrapper<>();queryWrapper.eq("user_id",user.getId());queryWrapper.eq("delete_status",0);queryWrapper.orderByDesc("createtime");List<Question> list=questionMapper.selectList(queryWrapper);log.debug("当前用户的问题数量为:{}",list.size());return list;}
}

步骤5:

编写完QuestionServiceImpl类中的代码

就可以在控制器中调用了,

控制器调用无需任何参数直接调用即可

第一次打开QuestionController类编写代码如下

@RestController
@RequestMapping("/v1/questions")
@Slf4j
public class QuestionController {@AutowiredIQuestionService questionService;//查询返回当前登录用户发布的问题@GetMapping("/my")public R<List<Question>> my(){log.debug("开始查询当前用户的问题");//这里要处理个异常,因为用户可能没有登录try{List<Question> questions=questionService.getMyQuestions();return R.ok(questions);}catch (ServiceException e){log.error("用户查询问题失败!",e);return R.failed(e);}}
}

编写到这里,我们就可以向浏览器编写路径

http://localhost:8080/v1/questions/my来看到控制返回的JSON格式信息

开发页面和JS代码显示问题

步骤1:

先在index.html页面中编写VUE代码准备绑定JSON格式信息

<div class="container-fluid" id="questionsApp"><h4 class="border-bottom m-2 p-2 font-weight-light"><i class="fa fa-comments-o" aria-hidden="true"></i> 我的问答</h4><div class="row" style="display: none"><div class="alert alert-warning w-100" role="alert">抱歉您还没有提问内容, <a href="question/create.html" class="alert-link">您可以点击此处提问</a>,或者点击标签查看其它问答</div></div><div class="media bg-white m-2 p-3" v-for="question in questions" ><div class="media-body w-50"><div class="row"><div class="col-md-12 col-lg-2"><span class="badge badge-pill badge-warning" style="display: none">未回复</span><span class="badge badge-pill badge-info" style="display: none">已回复</span><span class="badge badge-pill badge-success">已解决</span></div><div class="col-md-12 col-lg-10"><h5 class="mt-0 mb-1 text-truncate"><a class="text-dark" href="question/detail.html"v-text="question.title">eclipse 如何导入项目?</a></h5></div></div><div class="font-weight-light text-truncate text-wrap text-justify mb-2" style="height: 70px;"><p v-html="question.content">eclipse 如何导入项目?</p></div><div class="row"><div class="col-12 mt-1 text-info"><i class="fa fa-tags" aria-hidden="true"></i><a class="text-info badge badge-pill bg-light" href="tag/tag_question.html"><small >Java基础 &nbsp;</small></a></div></div><div class="row"><div class="col-12 text-right"><div class="list-inline mb-1 "><small class="list-inline-item"v-text="question.nickname">风继续吹</small><small class="list-inline-item"><span v-text="question.pageViews">12</span>浏览</small><small class="list-inline-item" >13分钟前</small></div></div></div></div><!-- / class="media-body"--><img src="img/tags/example0.jpg"  class="ml-3 border img-fluid rounded" alt="" width="208" height="116"></div><div class="row mt-2"><div class="col-6 offset-3"><nav aria-label="Page navigation example"><div class="pagination"><a class="page-item page-link" href="#" >上一页</a><a class="page-item page-link " href="#" >1</a><a class="page-item page-link" href="#" >下一页</a></div></nav></div></div></div>

步骤2:

js/index.js文件修改为

/*
显示当前用户的问题*/
let questionsApp = new Vue({el:'#questionsApp',data: {questions:[]},methods: {loadQuestions:function () {$.ajax({url: '/v1/questions/my',method: "GET",success: function (r) {console.log("成功加载数据");console.log(r);if(r.code === OK){questionsApp.questions = r.data;}}});}},created:function () {console.log("执行了方法");this.loadQuestions(1);}
});

随笔

内存操作是纳秒级别

硬盘操作是毫秒级别

1毫秒=1000微妙

1微秒=1000纳秒

内存和硬盘操作差着百万倍级别

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/79047.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker search 镜像报错: connect: no route to host (桥接模式配置静态IP)

如下 原因 可能有多种&#xff1a; ① 没有开放防火墙端口 ② ip地址配置有误 解决 我是因为虚拟机采用了桥接模式&#xff0c;配置静态ip地址有问题。 先确认虚拟机采用的是 桥接模式&#xff0c;然后启动虚拟机。 1、打开命令行&#xff0c;输入下面指令&#xff0c;打开…

远程访问桌面软件 OpenText Exceed TurboX(ETX)如何提高企业生产力

远程访问桌面软件 OpenText Exceed TurboX&#xff08;ETX&#xff09;如何提高企业生产力 几乎所有规模和行业的企业&#xff0c;员工的工作方式、时间和地点方面发生重大变化&#xff0c;这主要得益于新技术和全球商业与协作。业务领导者正在推动其 IT 部门提出解决方案&…

算法基础简介

目录 1、递归 2、二分查找 3、排序算法 分类 3.1、冒泡排序 3.2、选择排序 3.3、插入排序 3.4、希尔排序(高级插入排序) 3.5、归并排序 3.6、快速排序 核心思想 具体步骤 代码实现 3.7、堆排序 3.8、计数排序 3.9、桶排序 3.10、基数排序 4、字符串匹…

QT自带PDF库的使用

QT自带PDF库可以方便的打开PDF文件&#xff0c;并将文件解析为QImage&#xff0c;相比网上提供的开源库&#xff0c;QT自带PDF库使用更方便&#xff0c;也更加可靠&#xff0c;然而&#xff0c;QT自带PDF库的使用却不同于其他通用库的使用&#xff0c;具备一定的技巧。 1. 安装…

【深度学习】Transformer,Self-Attention,Multi-Head Attention

必读文章&#xff1a; https://blog.csdn.net/qq_37541097/article/details/117691873 论文名&#xff1a;Attention Is All You Need 文章目录 1、Self-Attention 自注意力机制2、Multi-Head Attention 1、Self-Attention 自注意力机制 Query&#xff08;Q&#xff09;表示当…

Docker Compose构建lnmp

目录 Compose的优点 编排和部署 Compose原理 Compose应用案例 安装docker-ce 阿里云镜像加速器 安装docker-compose docker-compose用法 Yaml简介 验证LNMP环境 Compose的优点 先来了解一下我们平时是怎么样使用docker的&#xff1f;把它进行拆分一下&#xff1a; 1…

全志F1C200S嵌入式驱动开发(soc系统集成)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 任何一个嵌入式设备都是由很多的子系统组成的。这里面有硬件、有软件,还可能有机械,并不一定就是大家看到的消费电子那样,即一个soc构成了所有的系统。现实情况是,要构建一个系…

网关 GateWay 的使用详解、路由、过滤器、跨域配置

一、网关的基本概念 SpringCloudGateway网关是所有微服务的统一入口。 1.1 它的主要作用是&#xff1a; 反向代理&#xff08;请求的转发&#xff09; 路由和负载均衡 身份认证和权限控制 对请求限流 1.2 相比于Zuul的优势&#xff1a; SpringCloudGateway基于Spring5中…

【JavaSE】面向对象编程思想之继承

【本节目标】 1. 继承 2. 组合 目录 1. 为什么需要继承 2. 继承概念 3. 继承的语法 4. 父类成员访问 4.1 子类中访问父类的成员变量 4.2 子类中访问父类的成员方法 5. super关键字 6. 子类构造方法 7. super和this 8. 再谈初始化 9. protected 关键字 10. 继承方式…

【C++基础(六)】类和对象(下)--初始化列表,友元,匿名对象

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C初阶之路⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; 类和对象 1. 前言2. 初始化列表2.1初始化列表的作用…

岩土工程监测仪器多通道振弦传感器信号转换器应用于铁路监测

岩土工程监测仪器多通道振弦传感器信号转换器应用于铁路监测 岩土工程监测是工程建设和运营过程中必不可少的环节&#xff0c;它主要是通过对地下水位、土体应力、变形、固结沉降等参数进行实时监测&#xff0c;以保证工程施工和运营的安全性和稳定性。而多通道振弦传感器信号…

【Segment Anything Model】四:预处理自己的数据集接入SAM

文章目录 1️⃣预备知识2️⃣实现思路&#x1f538;脚本预处理得到包含embedd和GT的npz&#x1f538;编写Dataset类3️⃣代码&#x1f538;实现脚本预处理得到包含embedd和GT的npz代码&#x1f538;实现Dataset的代码 1️⃣预备知识 欢迎订阅本专栏&#xff08;为爱发电&#…

Idea添加mybatis的mapper文件模版

针对Java开发人员&#xff0c;各种框架的配置模版的确是需要随时保留一份&#xff0c;在使用的时候&#xff0c;方便复制粘贴&#xff0c;但是也依然不方便&#xff0c;我们可以给开发工具&#xff08;IDE&#xff09;中添加配置模版&#xff0c;这里我介绍下使用idea开发工具&…

ad+硬件每日学习十个知识点(18)23.7.29 (LDO原理、LDO的补偿引脚)

文章目录 1.LDO名字介绍2.LDO的应用范围3.LDO的原理4.LDO输出端和输入端的差值至少满足多少V&#xff1f;怎么计算的&#xff1f;5.输出的误差和输出电流&#x1f446;&#xff08;右下角图像&#xff09;6.LDO一般会有个引脚是做补偿之用&#xff0c;datasheet会说明一个器件的…

Packet Tracer - 检验 IPv4 和 IPv6 编址

Packet Tracer - 检验 IPv4 和 IPv6 编址 地址分配表 设备 接口 IPv4 地址 子网掩码 默认网关 IPv6 地址/前缀 R1 G0/0 10.10.1.97 255.255.255.224 N/A 2001:DB8:1:1::1/64 N/A S0/0/1 10.10.1.6 255.255.255.252 N/A 2001:DB8:1:2::2/64 N/A 本地链路 F…

Linux 信号signal处理机制

Signal机制在Linux中是一个非常常用的进程间通信机制&#xff0c;很多人在使用的时候不会考虑该机制是具体如何实现的。signal机制可以被理解成进程的软中断&#xff0c;因此&#xff0c;在实时性方面还是相对比较高的。Linux中signal机制的模型可以采用下图进行描述。 每个进程…

电力巡检无人机助力迎峰度夏,保障夏季电力供应

夏季是电力需求量较高的时期&#xff0c;随着高温天气的来临&#xff0c;风扇、空调和冰箱等电器的使用量也大大增加&#xff0c;从而迎来夏季用电高峰期&#xff0c;电网用电负荷不断攀升。为了保障夏季电网供电稳定&#xff0c;供电公司会加强对电力设施设备的巡检&#xff0…

spring — Spring Security 5.7与6.0差异性对比

1. spring security Spring Security 是一个提供身份验证、授权和针对常见攻击保护的框架。 凭借对保护命令式和反应式应用程序的一流支持&#xff0c;它成为基于Spring的标准安全框架。 Spring Security 在最近几个版本中配置的写法都有一些变化&#xff0c;很多常见的方法都…

【力扣每日一题】2023.8.7 反转字符串

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们一个字符数组形式的字符串&#xff0c;让我们直接原地修改反转字符串&#xff0c;不必返回。 给出的条件是使用O(1)的额外空间…

24届近5年重庆邮电大学自动化考研院校分析

今天给大家带来的是重庆邮电大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、重庆邮电大学 学校简介 重庆邮电大学简称"重邮"&#xff0c;坐落于直辖市-重庆市&#xff0c;入选国家"中西部高校基础能力建设工程”、国家“卓越工程师教育培养计划…