美文网首页
[JWeb系列4] SpringBoot注册登录小测试

[JWeb系列4] SpringBoot注册登录小测试

作者: 做梦枯岛醒 | 来源:发表于2018-01-05 11:19 被阅读2343次

    SpringBoot+MyBatis+Thymeleaf注册登录

    好吧我承认,我用Php Web的时候也是做的注册登录,现在写javaweb还是注册登录,如果是仅仅做一个简单的注册登录不考虑安全性等问题,那其实拿来做练手是很不错的。

    下面要完成的是这几项。
    • 准备
    • View
    • get/post
    • 注册登录分析
    • 注册登录实现
    • 总结

    1.准备

    用JavaWeb来写的话比Php肯定是复杂的多,特别是对于我第一次接触JavaWeb的小白,所以我们这篇文章不得不长篇大论的写,如果你喜欢研究的话,不如耐心的看下来,如果您是大神的话,还请您能够指出其中的错误。

    准备就是我们打算接着使用先前建立好的工程,我们新建几个控制器来做注册登录。

    那么在写代码之前我们要学会一些基本的知识。

    2.View

    MVC想必大家应该很熟悉,特别是我们用的SpringBoot框架,更应该知道它是基于MVC架构的。
    上面我们已经写过C,这次我们来研究一下View。

    先贴一段Controller的代码

    package com.example.demo.Web;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.servlet.ModelAndView;
    @RestController
    @RequestMapping("/My")
    public class MyController {
        @RequestMapping(value = "/index")
        public ModelAndView hello(Model model) {
            model.addAttribute("name", "苏凌");
            return new ModelAndView("hello");
        }
        @RequestMapping("/")
        public String normal()
        {
            return "hello";
        }
    }
    

    这里就是写好了两个接口,访问http://localhost:8080/My/的时候是打印hello,访问http://localhost:8080/My/index时候截图如下

    运行

    那么这个界面从哪来的?

    你可能已经知道了

    new ModelAndView("hello")
    

    这行代码应该就是打印的内容吧。
    对,没错,通过ModelAndView方法,我们可以找到hello代表的网页,然后把网页里面的信息展示出来,同时我们可以通过model传递数据,那么我们此时就做到了模型视图分离。

    那么我们用到的就是模板技术(Jsp开发应该不属于模板系列)。

    Tip: 目前Spring官方已经不推荐使用JSP来开发WEB了,而是推荐使用如下几种模板引擎来开发:

    • Thymeleaf(Spring官方推荐)
    • FreeMarker
    • Velocity
    • Groovy
    • Mustache
      顾名思义,采用模板我们可以更高效,准确的实现页面,也做到了对于后期维护的前提。我们可以选择自己喜欢的模板,大同小异

    Thymeleaf

    那么这篇文章里,我们使用官方推荐模板,关于这款模板的好处大家可以自行搜索,在这里不占用篇幅。

    第一步:下载

    通过修改pom.xml添加Thymeleaf的依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    
    Note:注意加在<dependencies></dependencies>标签里

    下载需要挺长时间,如果等不及或者多次不成功可以试试修改mvn源。
    我们下载完最好检验一下有没有成功(我踩了一天的坑,就是因为没有下载成功,pom写的没毛病,就是lib下载不完整……坑的一批),打开mvn project,看看有没有Thymeleaf。


    显示

    有的话继续,没有的话慢慢下载……暂时没啥好方法。

    第二步,小小配置

    在application.properties中添加一行,小小的配置关闭缓存。

    #关闭缓存
    spring.thymeleaf.cache=false
    
    第三步,编写模板文件
    Note:文件需要放在src/main/resouces/templates/目录下,文件后缀.html

    上面的例子中我写的模板文件是hello.html

    <!DOCTYPE HTML>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>hello</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    </head>
    <body>
    <!--${name}可以打印一个叫name的变量-->
    <p th:text="'你好!' + ${name} + '!'" ></p>
    </body>
    </html>
    

    模板语法不在这里多介绍,暂时先Copy代码,我们这篇文章理解一下流程。

    第四步,编写Controller

    那么Controller就是我们上面贴的那个,我们只看所需要的接口

    package com.example.demo.Web;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.servlet.ModelAndView;
    @RestController
    @RequestMapping("/My")
    public class MyController {
        @RequestMapping(value = "/index")
        public ModelAndView hello(Model model) {
            model.addAttribute("name", "苏凌");
            return new ModelAndView("hello");
        }
    }
    

    我们使用model传入了name变量的值,然后用ModelAndView显示了页面。

    这里还有一种操作,就是下面这种直接返回html名字的写法,但是要求必须使用@Controller注解。


    image.png

    Thymeleaf先说到这里,在后面我们可能会尝试一下Jsp原始写法。

    3.get/post

    1.准备

    那么研究Web,必须先来研究get/post请求。
    【文章参考:http://blog.csdn.net/u010399316/article/details/52913299

    我们最常用的两种方式。

    比如说我设计这样一个链接。
    http://localhost:8080/register?name=surine&pwd=123 通过get请求,传递用户名和密码来完成注册,
    然后设计这样一个链接。
    http://localhost:8080/login 通过post请求,传递用户名和密码来完成登录。

    2.Get

    在SpringBoot中,我们的Get这样实现,通过method来设置方法

    /**
         * 通过get请求去注册
         * @param name
         * @param pwd
         * @return 状态信息
         */
        //method :设置一下get或者post
        //@RequestParam的注解已经很清楚了,接受名字为name的参数,required 设置是否必须。
        @RequestMapping(value = "/register", method = RequestMethod.GET)
        public String register(@RequestParam(value = "name", required = true) String name,
                                 @RequestParam(value = "pwd", required = true) String pwd) {
            //register_check是自定义的一个注册方法我们可以在里面写注册操作,返回状态码
            return register_check(name, pwd);
        }
    
    //先写一个简单的register_check方法
    private String register_check(String name, String pwd) {
            if(name.equals("surine")&&pwd.equals("123456")){
                return "注册成功";
            }else{
                return "注册失败";
            }
        }
    

    我们浏览器测试一下
    首先我们不给参数看啥情况,下面报错很明显,缺少参数,这是因为我们设置了必须要参数的原因


    image.png

    账号密码错误


    image.png

    账号密码正确


    image.png

    细心的小朋友站出来:哪家的注册还判断你的账号密码……
    我:测试嘛!这么认真干嘛!

    3.Post

    我们先写一个Post的Controller,额,竟然跟Get一样,除了改了下method

    /**
         * 通过get请求去登陆
         *
         * @param name
         * @param pwd
         * @return
         */
        @RequestMapping(value = "/login", method = RequestMethod.POST)
        public String login(@RequestParam(value = "name", required = true) String name,
                                 @RequestParam(value = "pwd", required = true) String pwd) {
            return login_check(name, pwd);
        }
    
        private String login_check(String name, String pwd) {
            if(name.equals("surine")&&pwd.equals("123456")){
                return "登录成功";
            }else{
                return "登录失败";
            }
        }
    

    那么我们跑起来用Postman来测试一下。


    image.png

    输入地址,表单,最后得到结果。
    看样子没有什么异常,暂时先掌握这些,为我们后面的开发做铺垫。

    其余的方法感兴趣可以自行研究。

    4.注册登录分析

    Note:注意,我们在下面写的代码可能与上面有所不同,具体为什么这么写我会在下面做出解释,但是上面的练习也应该跑一遍,参考:https://www.jianshu.com/p/212f2682c10b
    这里面提到的一些生词,在一会都会详细解释,现在就记住我们要写的项目有这么些东西就行了。

    1.原型分析

    预期要做成下面这个样子,


    首页.png

    打开首页有登录注册两个链接,点击登录链接,跳转到登录,登录成功失败会有相应提示,同理注册也是。


    注册.png
    密码错误.png
    2.流程分析

    最终的文件结构如下图所示。


    image.png

    这里我们有5个重要部分
    Controller上面我们讲了,作为接受页面数据的工具,Dao是操作数据库的工具,Domin是放的实体类,Service主要是操作数据检查合法性,通过Service来发出指令,templates也就是我们的页面模板了。

    注册(登录与其相同):

    • 前端页面(templates)把用户的注册信息传递给Controller
    • Conteoller把注册信息交给Service去处理
    • Service里面和Dao层一起处理业务逻辑(结合数据库判断数据合法性)
    • Service把处理结果返回给Controller
    • Controller在把结果传递给前端页面,这是用户就能看见注册结果了
      C->V->M->V->C 的流程不多说了。
    3.设计原则

    可能你会觉得我一个模板,一个Controller,然后用Mapper(上篇文章讲过)就可以做一个注册登录,搞得这么复杂干嘛……
    这样写体现了MVC模型的特点,通过对业务的一些分层,减少层次之间耦合,使每一个类的功能单一化,方便以后维护,但对于新手来说,一下子接受不了,

    4.数据库设计

    数据库不多说了,自己建立就行了,不会搞数据库的童鞋,还是先去搞搞数据库吧。


    数据表

    5.注册登录实现

    下面我们开始Coding,在这期间遇到了不少问题,但是又没做什么解决自己就好了……真的是要人命,然后我会在遇到问题或者容易出错的地方打Tips,童靴们自己注意下。

    1.配置项

    首先我们做一下配置,把这之前的一起说了。
    Thymeleaf模板:

    #修改pom.xml文件
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    
    #修改application.properties文件
    #为了保证项目的运行,增加这些
    spring.thymeleaf.prefix=classpath:/templates/
    spring.thymeleaf.suffix=.html
    spring.thymeleaf.mode=HTML5
    spring.thymeleaf.servlet.content-type=text/html
    
    #关闭缓存
    spring.thymeleaf.cache=false
    

    Application:作为SpringBoot的入口文件也有需要配置的地方
    添加mapper扫描的包路径,为数据库连接做准备

    @SpringBootApplication
    //Mapper扫描(这里的值就是dao目录的值,按照我刚贴的目录结构来做就行)
    @MapperScan("com.example.demo.dao")
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    }
    
    2.实体类

    刚才说过,domin目录下面放实体类,我们第一步先把实体类做出来,为整体的流程做协调,根据我们的数据库设计字段,来设计实体类。

    Tip: 没有什么特殊需求,一定要保持数据库字段跟domin实体类字段一致,甚至是数据类型,省的出现各种各样的问题。
    我的User.class

    package com.example.demo.domin;
    public class User {
        private int id;
        private String username;
        private String password;
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
    }
    
    3.数据库操作

    前面也说过,Dao目录下面放的各种dao文件是我们的数据库操作接口(抽象数据类),例如我们的UserDao内容如下,两个操作,增加用户,查询用户。
    所以在以后的项目中,如果需求大的话,我们可以编写更多功能。

    package com.example.demo.dao;
    
    //这个注解代表这是一个mybatis的操作数据库的类
    @Repository
    
    public interface UserDao {
        // 根据username获得一个User类
        @Select("select * from user where username=#{name}")
        User getOneUser(String name);
    
    
        //插入一个User
        @Insert("insert into user (username,password) values(#{username},#{password})")
        boolean setOneUser(User user);
    
    }
    

    Tip:注意字段对应 比如#{name}最后会被String name 的name所替换

    4.API接口(Controller)

    这里是重点,前端后端从这里划分(不知道这个说法正不正确,个人见解),我们根据需求分析,发现需要实现的功能主要有三个,注册登录注销,那么我们的Controller如下。(UserService 先让他标红,我们将在下面建立)

    package com.example.demo.controller;
    @Controller
    @EnableAutoConfiguration
    public class IndexController {
        //自动注入userService,用来处理业务
        @Autowired
        private UserService userService;
         /**
          * 域名访问重定向
          * 作用:输入域名后重定向到index(首页)
          * */
        @RequestMapping("")
        public String index(HttpServletResponse response) {
            //重定向到 /index
            return response.encodeRedirectURL("/index");
        }
        /**
         * 首页API
         * 作用:显示首页
         * */
        @RequestMapping("/index")
        public String home(Model model) {
            //对应到templates文件夹下面的index
            return "index";
        }
        /**
         * 注册API
         * @method:post
         * @param user(从View层传回来的user对象)
         * @return 重定向
         * */
        @RequestMapping(value = "/register", method = RequestMethod.POST)
        public String registerPost(Model model,
                                   //这里和模板中的th:object="${user}"对应起来
                                   @ModelAttribute(value = "user") User user,
                                   HttpServletResponse response) {
            //我们可以用Sout这种最原始打印方式来检查数据的传输
            System.out.println("Controller信息:"+user.getUsername());
            System.out.println("Controller密码:"+user.getPassword());
            //使用userService处理业务
            String result = userService.register(user);
            //将结果放入model中,在模板中可以取到model中的值
            //这里就是交互的一个重要地方,我们可以在模板中通过这些属性值访问到数据
            model.addAttribute("result", result);
            //开始重定向,携带数据过去了。
            return response.encodeRedirectURL("/index");
        }
        /**
         * 登录API
         * @method:post
         * @param user(从View层传回来的user对象)
         * @return 重定向
         * */
        @RequestMapping(value = "/login", method = RequestMethod.POST)
        public String loginPost(Model model,
                                @ModelAttribute(value = "user") User user,
                                HttpServletResponse response,
                                HttpSession session) {
            String result = userService.login(user);
            if (result.equals("登陆成功")) {
               //session是作为用户登录信息保存的存在
                session.setAttribute("user",user);
            }
            model.addAttribute("result", result);
            return response.encodeRedirectURL("/index");
        }
        /**
         * 注销API
         * @method:get
         * @return 首页
         * */
        @RequestMapping(value = "/loginOut", method = RequestMethod.GET)
        public String loginOut(HttpSession session) {
            //从session中删除user属性,用户退出登录
            session.removeAttribute("user");
            return "index";
        }
    }
    

    相信就算是小白,我们在前面的学习中也接触到接口的写法了,这里仅仅增加了几个重定向的方法,还有post的写法有一点点不太一样(运用了模板之后)

    Tip:不会使用单元测试或调试的话可以用System.out.print这种最原始的方法来检查数据哦

    5.页面模板

    通过需求分析我们一共要设计三个页面,源码分别如下。

    <!--index.html-->
    <!--模板源码应该很好理解,不理解的话去看看教程就OK-->
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
    <!--这里result会报错,不要担心这是idea的bug,不影响你的项目->
    <h1> <span th:text="${result}"></span></h1>
    <h1>欢迎 : <span  th:text="${session.user}?${session.user.getUsername()}:'(您未登录)'" ></span> </h1>
    <a th:href="@{/register}">点击注册</a>
    <a th:href="@{/login}" th:if="${session.user==null}">点击登录</a>
    <a th:href="@{/loginOut}" th:unless="${session.user==null}">退出登陆</a>
    </body>
    </html>
    
    <!--login.html-->
    
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>登陆</title>
    </head>
    <body>
    <h1>欢迎登陆</h1>
     <!--这个地方user也会报错,不用担心-->
    <!--注意下面name,和id都写上就OK-->
    <form th:action="@{/login}" th:object="${user}" method="post">
        <label for="username">username:</label>
        <input type="text" name="username"  id="username" />
        <label for="password">password:</label>
        <input type="text" name="password" id="password" />
        <input type="submit" value="submit">
    </form>
    </body>
    </html>
    
    <!--register.html-->
    
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>欢迎注册</title>
    </head>
    <body>
    <h1>欢迎注册</h1>
    <form th:action="@{/register}" th:object="${user}" method="post">
        <label for="username">username:</label>
        <input type="text" id="username" name="username"/>
        <label for="password">password:</label>
        <input type="text" id="password" name="password"/>
        <input type="submit" value="submit">
    </form>
    </body>
    </html>
    

    TIp:页面的重点放在input的一些属性上,我们输入的值最终会被映射到user(domin)里面

    6.Service

    写了好长时间,算是把页面,数据库,接口都写了,那么剩下最后一个纽带就是service了。

    package com.example.demo.service;
    
    import com.example.demo.dao.UserDao;
    import com.example.demo.domin.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService {
        //自动注入一个userDao
        @Autowired
        private UserDao userDao;
    
        //用户注册逻辑
        public String  register(User user) {
            System.out.println(user.getUsername());
            User x = userDao.getOneUser(user.getUsername());
            //判断用户是否存在
            if (x == null) {
                userDao.setOneUser(user);
                return "注册成功";
            }
            else {
                return x.getUsername()+"已被使用";
            }
        }
        //用户登陆逻辑
        public String login(User user) {
            //通过用户名获取用户
            User dbUser = userDao.getOneUser(user.getUsername());
    
            //若获取失败
            if (dbUser == null) {
                return "该用户不存在";
            }
            //获取成功后,将获取用户的密码和传入密码对比
            else if (!dbUser.getPassword().equals(user.getPassword())){
                return "密码错误";
            }
            else {
                //若密码也相同则登陆成功
                //让传入用户的属性和数据库保持一致
                user.setId(dbUser.getId());
                return "登陆成功";
            }
        }
    }
    

    仔细阅读service的源码,你就会发现,它其实就是与dao联系起来做数据合法性检验的。

    Tip:这里也是可以使用sout来测试数据

    7.运行
    到这里我们的所有代码都已经写完了,如果你的工程还缺了什么跑不起来,可以在下面评论哦。
    运行的时候浏览器输入localhost:8080就可以到首页,经我这边测试注册登录注销都没问题,而且登录了之后下次再访问就直接是登录状态了(session没有设置过期时间,所以直到下一个用户登录一直有效)


    image.png

    Tip:善于观察浏览器报错信息或者Idea里也有,通过检查报错来解决问题,不要遇到问题就去对照别人的源码看哪里不一样,同样的代码可能不适合你。

    6.总结

    感觉还是Php写起来简单一些,毕竟脚本语言本身就是轻巧。
    那么JavaWeb用了SpringBoot框架后,也从一定程度上减少了代码的复杂度,逻辑还算清楚。
    唯一不爽的是数据库竟然要自己写sql语句……
    不过自由定制毕竟是可以满足大量需求的,那么如果你真的不喜欢sql语句,可以试试用 Hibernate来替换MyBatis

    我们目前实现的是一个注册登录功能,那么其实你再做别的接口也是一样的,只是在它的业务上有一些不同,那么希望这篇文章能对你有所帮助。

    个人刚接触JavaWeb,有好多东西也是现查现学,因为为了实习才准备的JavaWeb,所以现在连本书都没有,好尴尬。

    最后,代码虐我千百遍,我对代码如初恋。

    这里特意加出一个部分,我们来讨论一下Jsp的写法和Css/js静态页面(仅讨论JSP与Css/js,不讨论thymeleaf)的解决方案。

    SpringBoot与Jsp

    前面我们说到Spring官方非常推荐开发者使用ThymeLeaf来开发,而不推荐使用Jsp。那我们还是要了解一下Jsp是怎么写的。

    1.导入依赖

    再pom.xml里面导入依赖

    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
    </dependency>
    

    记得导完看看有没有哦,这里我先前一直不知道要导入这个,说实话我真的没找到一个像样的文章,也不知道是我理解能力太差了还是大家都写得很烂,自我感觉良好…… 我不知道我写的是不是很烂,但是我把我做的每一步都说出来了。如果还有问题你可以私信或留言。
    参考:https://stackoverflow.com/questions/29782915/spring-boot-jsp-404
    如果不导入就会出现这位小哥遇到的错误,也就是我一直遇到的错误

    image.png
    我是参考第一个红框和第三个红框来解决的,也就是上面的代码。

    Tip:遇到问题不要百度,要么google要么直接StackOverFlow,百度出来的?要是中国程序员都这么糟糕的话……简直不敢想象。

    2.配置application.properties

    文件中添加这两行

    # 页面默认前缀目录
    spring.mvc.view.prefix=/WEB-INF/jsp/
    # 响应页面默认后缀
    spring.mvc.view.suffix=.jsp
    
    3.配置Application

    主要增加一个继承


    增加
    4.新建文件夹,创建jsp

    webapp/WEB-INF/jsp/文件


    webapp

    举个例子,indexjsp.jsp内容

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Spring Boot Sample</title>
    </head>
    <body>
    Time: ${time}
    <br>
    Message: ${message}
    </body>
    </html>
    
    5.Controller
     @RequestMapping(value = "/jsp/index",method = RequestMethod.GET)
        public String jsp_index(Map<String, Object> model){
            model.put("time", new Date());
            model.put("message", "你好");
            return "indexjsp";
        }
    
    
    6.访问

    访问之前有个小Tip

    Tip:注意删掉Thymeleaf在工程中的依赖和配置,这两样就行。

    要注意Thymeleaf和jsp是两种并列的技术,为了解决同一个问题,不要试图去融合使用他们,那样只会让你的项目更乱,所以我们使用的时候按照需求选一个就行,我不确定两个共存会不会出现致命错误,但是为了增加系统的稳定性,尽量不要两个一起使用。
    地址:localhost:8080/jsp/index


    image.png

    Jsp与CSS

    在Jsp中使用静态资源也没什么难处。

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Spring Boot Sample</title>
        <!--Import Google Icon Font-->
        <link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
        <!--Import materialize.css-->
        <link type="text/css" rel="stylesheet" href="../../static/css/materialize.css"  media="screen,projection"/>
    </head>
    <body>
    <script type="text/javascript" src="../../static/js/jquery-3.2.1.js"></script>
    <script type="text/javascript" src="../../static/js/materialize.js"></script>
    Time: ${time}
    <br>
    Message: ${message}
    <button class="btn waves-effect waves-light" type="submit" name="action">提交
        <i class="material-icons right">send</i>
    </button>
    </body>
    </html>
    

    上面这个代码还是indexjsp.jsp,我们在其中引入了materialize和jquery(materialize需要),然后使用了materialize中的一个组件。
    重点在我们建立的文件夹,把materialize放在static下面



    效果:


    image.png

    不会用materialize的童鞋参考中文网http://www.materializecss.cn/buttons.html。哈哈不罗嗦了,好长一篇文章,最后给一个jsp的注册登录版本源码。

    https://github.com/Surine/demo

    相关文章

      网友评论

          本文标题:[JWeb系列4] SpringBoot注册登录小测试

          本文链接:https://www.haomeiwen.com/subject/ttmhnxtx.html