网站建设策划怎么谈,宝安西乡网站建设,精品成品网站1688,做公众号封面图的网站【开源项目--稻草】Day04 1. 续 VUE1.1 完善VUEAJAX完成注册功能 Spring验证框架什么是Spring验证框架使用Spring-Validation 稻草问答-学生首页显示首页制作首页的流程开发标签列表标签列表显示原理 从业务逻辑层开始编写控制层代码开发问题列表开发业务逻辑层开发页面和JS代码… 【开源项目--稻草】Day04 1. 续 VUE1.1 完善VUEAJAX完成注册功能 Spring验证框架什么是Spring验证框架使用Spring-Validation 稻草问答-学生首页显示首页制作首页的流程开发标签列表标签列表显示原理 从业务逻辑层开始编写控制层代码开发问题列表开发业务逻辑层开发页面和JS代码显示问题 随笔 1. 续 VUE
1.1 完善VUEAJAX完成注册功能
我们现在注册用户只能在浏览器控制台看到结果
怎么能再注册页面上看到注册结果呢?
实际上,register.html页面已经准备好了一个显示注册信息的div
改写它代码如下
div iderror classalert alert-dangerstyledisplay: nonev-bind:class{d-block:hasError}i classfa fa-exclamation-triangle/ispan v-textmessage邀请码错误/span
/div其中v-bind:class{‘d-block’:hasError}的含义为
根据Vue代码中绑定的hasError变量来决定是否将classd-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.hasErrortrue;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.messager.message;app.hasErrortrue;}}});}}
});新增两个属性:hasError和message
这两个属性控制页面上是否显示错误div以及错误div中出现的提示信息是什么
Spring验证框架
什么是Spring验证框架
Spring提供的对用户输入信息进行验证的框架组件
是服务器端验证技术 使用Spring验证框架验证发送到服务器的内容的合法性!
Spring-validation(验证)
使用Spring-Validation
步骤1:
导入依赖
子项目pom.xml文件添加:
!-- 验证框架 --
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-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 errorvalidaResult.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.制作学生信息面板
开发标签列表
标签列表显示原理
在用户已经能够登录显示主页的前提下
主页页面中编写ajax向控制器发送请求所有标签控制接到请求后调用业务逻辑层业务逻辑层从tagMapper接口查询所有标签业务逻辑层将查询到的信息返回给控制器控制器获得所以标签返回JSON格式ajax中获得JSON对象,利用VUE绑定显示在页面上
从业务逻辑层开始
我们可以选择先编写业务逻辑层
步骤1:
ITagService接口中添加方法
public interface ITagService extends IServiceTag {ListTag getTags();
}步骤2:
实现这个接口
TagServiceImpl类中代码如下
Service
public class TagServiceImpl extends ServiceImplTagMapper, Tag implements ITagService {//CopyOnWriteArrayList是线程安全的集合,适合在高并发的环境下使用private final ListTag tagsnew CopyOnWriteArrayList();Overridepublic ListTag 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() {ListTag 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 RListTag tags(){ListTag listtagService.getTags();return R.ok(list);}
}步骤2:
到页面中(index.html)绑定vue需要的变量
页面代码如下 div classnav font-weight-light idtagsAppa hreftag/tag_question.html classnav-item nav-link text-info small全部/small/a!-- v-for 循环中in左侧是随意起的变量名,会在循环体中使用in右侧的变量名,绑定这VUE代码中的变量--a hreftag/tag_question.htmlclassnav-item nav-link text-infov-fortag in tagssmall v-texttag.nameJava基础/small/a/div步骤3:
index.html网页的结束位置要引入两个js文件
/body
script srcjs/utils.js/script
script srcjs/index.js/script
script srcjs/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 IServiceQuestion {//按登录用户查询当前用户问题的方法ListQuestion getMyQuestions();
}步骤2:
要想实现查询当前登录的用户信息,必须使用Spring-Security提供的指定方法
调用这个方法的代码可能在项目后面的业务中也需要
这样写字QuestionService中就不合适了,所以我们先在IUserService中添加一个获得当前登录用户名的方法
IUserService添加代码 //从Spring-Security中获得当前登录用户的用户名的方法String currentUsername();
步骤3:
在UserServiceImpl类中实现获得当前登录用户名并返回
Overridepublic String currentUsername() {//利用Spring-Security框架获得当前登录用户信息Authentication authenticationSecurityContextHolder.getContext().getAuthentication();//判断当前用户有没有登录,如果没有登录抛出异常if(!(authentication instanceof AnonymousAuthenticationToken)){//上面代码是判断当前用的抽象权限类型是不是匿名用户//如果不是匿名用户,就是登录的用户,只有登录的用户才能返回用户名String usernameauthentication.getName();return username;}//没运行上面的if证明用户没有登录,抛出异常即可throw ServiceException.notFound(没有登录);}步骤4:
现在就可以在QuestionServiceImpl类中调用上面编写的方法来获得当前登录用户了
在根据这个用户信息(id)查询这个用户的问题
代码如下
Service
Slf4j
public class QuestionServiceImpl extends ServiceImplQuestionMapper, Question implements IQuestionService {AutowiredIUserService userService;AutowiredUserMapper userMapper;AutowiredQuestionMapper questionMapper;//按登录用户查询当前用户问题的方法Overridepublic ListQuestion getMyQuestions() {//获得当前登录用户的用户名String usernameuserService.currentUsername();log.debug(当前登录用户为:{},username);//如果已经登录,使用之前编写好的findUserByUsername方法//查询出当前用户的详细信息(实际上主要需要用户的id)User useruserMapper.findUserByUsername(username);if(user null){throw ServiceException.gone(登录用户不存在);}log.debug(开始查询{}用户的问题,user.getId());QueryWrapperQuestion queryWrappernew QueryWrapper();queryWrapper.eq(user_id,user.getId());queryWrapper.eq(delete_status,0);queryWrapper.orderByDesc(createtime);ListQuestion listquestionMapper.selectList(queryWrapper);log.debug(当前用户的问题数量为:{},list.size());return list;}
}步骤5:
编写完QuestionServiceImpl类中的代码
就可以在控制器中调用了,
控制器调用无需任何参数直接调用即可
第一次打开QuestionController类编写代码如下
RestController
RequestMapping(/v1/questions)
Slf4j
public class QuestionController {AutowiredIQuestionService questionService;//查询返回当前登录用户发布的问题GetMapping(/my)public RListQuestion my(){log.debug(开始查询当前用户的问题);//这里要处理个异常,因为用户可能没有登录try{ListQuestion questionsquestionService.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 classcontainer-fluid idquestionsApph4 classborder-bottom m-2 p-2 font-weight-lighti classfa fa-comments-o aria-hiddentrue/i 我的问答/h4div classrow styledisplay: nonediv classalert alert-warning w-100 rolealert抱歉您还没有提问内容 a hrefquestion/create.html classalert-link您可以点击此处提问/a或者点击标签查看其它问答/div/divdiv classmedia bg-white m-2 p-3 v-forquestion in questions div classmedia-body w-50div classrowdiv classcol-md-12 col-lg-2span classbadge badge-pill badge-warning styledisplay: none未回复/spanspan classbadge badge-pill badge-info styledisplay: none已回复/spanspan classbadge badge-pill badge-success已解决/span/divdiv classcol-md-12 col-lg-10h5 classmt-0 mb-1 text-truncatea classtext-dark hrefquestion/detail.htmlv-textquestion.titleeclipse 如何导入项目/a/h5/div/divdiv classfont-weight-light text-truncate text-wrap text-justify mb-2 styleheight: 70px;p v-htmlquestion.contenteclipse 如何导入项目/p/divdiv classrowdiv classcol-12 mt-1 text-infoi classfa fa-tags aria-hiddentrue/ia classtext-info badge badge-pill bg-light hreftag/tag_question.htmlsmall Java基础 nbsp;/small/a/div/divdiv classrowdiv classcol-12 text-rightdiv classlist-inline mb-1 small classlist-inline-itemv-textquestion.nickname风继续吹/smallsmall classlist-inline-itemspan v-textquestion.pageViews12/span浏览/smallsmall classlist-inline-item 13分钟前/small/div/div/div/div!-- / classmedia-body--img srcimg/tags/example0.jpg classml-3 border img-fluid rounded alt width208 height116/divdiv classrow mt-2div classcol-6 offset-3nav aria-labelPage navigation examplediv classpaginationa classpage-item page-link href# 上一页/aa classpage-item page-link href# 1/aa classpage-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纳秒
内存和硬盘操作差着百万倍级别