【开源项目--稻草】Day04

这篇具有很好参考价值的文章主要介绍了【开源项目--稻草】Day04。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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提供的对用户输入信息进行验证的框架组件

是服务器端验证技术

【开源项目--稻草】Day04,开源项目学习,开源

使用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.制作学生信息面板

开发标签列表

标签列表显示原理

【开源项目--稻草】Day04,开源项目学习,开源

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

  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<>();

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

    @Autowired
    ITagService tagService;
    @Test
    public 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 {

    @Autowired
    private 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 () {
        //页面加载完毕,立即调用loadTags
        this.loadTags();
    }
});

开发问题列表

了解开发流程

【开源项目--稻草】Day04,开源项目学习,开源

开发业务逻辑层

步骤1:

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

IQuestionService接口给中声明方法

public interface IQuestionService extends IService<Question> {

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

步骤2:

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

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

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

IUserService添加代码

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

步骤3:

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

@Override
    public 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 {
    @Autowired
    IUserService userService;
    @Autowired
    UserMapper userMapper;
    @Autowired
    QuestionMapper questionMapper;
    //按登录用户查询当前用户问题的方法
    @Override
    public 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 {
    @Autowired
    IQuestionService 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纳秒

内存和硬盘操作差着百万倍级别文章来源地址https://www.toymoban.com/news/detail-630560.html

到了这里,关于【开源项目--稻草】Day04的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端TypeScript学习day04-交叉类型与泛型

    (创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)            目录 交叉类型 泛型 创建泛型函数 调用泛型函数: 简化调用泛型函数: 泛型约束  指定更加具体的类型 添加约束  泛型接口  泛型类 泛型工具类型  Partial 

    2024年02月08日
    浏览(44)
  • Day-04 从 0 开始搭建一套规范的 Vue3.x 项目工程环境

    1.安装  2.按需引用 借助插件 babel-plugin-import 可以实现按需加载组件,减少文件体积。首先安装,并在文件  .babelrc  或者在 webpack  babel-loader  中配置:   3.main.ts 中注册使用 提交代码的说明同样进行了规范限制,采用 commitizen 提交规范,commitizen 需要进行单独安装,安装

    2024年02月07日
    浏览(36)
  • 根据cadence设计图学习硬件知识day04了解一些芯片

            PI3PCIE3212是PCIe Gen3.0、8Gbps、4对2差分,PCI ExpressR 3.0性能,8.0Gbps  双向信道多路复用器/多路分解器开关。由于其低的位对位偏斜,高的通道对通道噪声隔离双向操作和带宽,该产品是PCI Express°3.0信号的理想选择3dB带宽:8.1GHz以8.0Gbps进行切换。低位到位倾斜,最大

    2023年04月22日
    浏览(70)
  • 【SAP UI5 控件学习】DAY04 Input组Part IV 完结&&List组Part I

    和Data Picker类似,Time Picker允许用户选择相应的时间。 它有以下一些比较常用的属性。 value 用于显示Input中的时间的值,这个属性只能接受字符串的值,如果是 UI5.getInstance() 获取到的时间,需要转化成相应的字符串才可以 valueFormat 用于设置显示日期的格式,这个格式会影响

    2024年02月13日
    浏览(44)
  • 【学习笔记】java项目—苍穹外卖day11

    Apache ECharts 营业额统计 用户统计 订单统计 销量排名Top10 功能实现: 数据统计 数据统计效果图: 1.1 介绍 Apache ECharts 是一款基于 Javascript 的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。 官网地址:https://echarts.apache.org/zh/index.html 常见效果

    2024年04月09日
    浏览(47)
  • 【开源与项目实战:开源实战】79 | 开源实战二(中):从Unix开源开发学习应对大型复杂项目开发

    我们知道,项目越复杂、代码量越多、参与开发人员越多、开发维护时间越长,我们就越是要重视代码质量。代码质量下降会导致项目研发困难重重,比如:开发效率低,招了很多人,天天加班,出活却不多;线上 bug 频发,查找 bug 困难,领导发飙,中层束手无策,工程师抱

    2024年02月11日
    浏览(57)
  • 黑马头条项目学习--Day3: 自媒体文章发布

    自媒体后台搭建 ①:资料中找到heima-leadnews-wemedia.zip解压 拷贝到heima-leadnews-service工程下,并指定子模块 执行leadnews-wemedia.sql脚本 添加对应的nacos配置 ②:资料中找到heima-leadnews-wemedia-gateway.zip解压 拷贝到heima-leadnews-gateway工程下,并指定子模块 添加对应的nacos配置 图片上传的

    2024年02月13日
    浏览(67)
  • itheima苍穹外卖项目学习笔记--Day1:项目介绍与开发环境搭建

    (1). 前端环境搭建 前端工程基于 nginx 运行 启动nginx:双击 nginx.exe 即可启动 nginx 服务,访问端口号为 80 (2). 后端环境搭建 后端工程基于 maven 进行项目构建,并且进行分模块开发 (3). 前后端联调 修改数据库中明文密码,改为MD5加密后的密文 修改Java代码,前端提交的密码进行

    2024年02月15日
    浏览(38)
  • 聊聊如何学习开源项目

    工作几年的程序员同学,有了一定的项目经验,对于编程也有了自己的理解,但他们偶尔也会感到困惑,不知道接下来该如何提升自己。 在笔者看来:“这个阶段的程序员最需要的是提升自身编程能力和视野高度,而学习开源项目是最有效的方法之一”。 这篇文章,笔者聊

    2023年04月14日
    浏览(36)
  • 如何学习开源项目

    请注意,在开始学习开源项目之前,最好有过项目经验,不然在阅读开源项目代码的时候可能会有点痛苦,特别是比较大一点的开源项目。 一般我们在学习的过程中,总是少不了项目的实战学习,那么如何学习到好的开源项目呢? 在这里我们拿Gitee举例子(因为GitHub太慢了)

    2024年02月02日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包