目录
第一步环境搭建
后端:
前端:
第二步画流程图
web:
service:
dao层:
第三步前端代码的实现
这是开始的页面,接下来我们要到router路由下书写#login的路径
路由中的component在我们自己创建的views书写vue文件
#/success的success.vue文件
第四步:后端代码的实现
web层loginServer类
web层registerServlet类
service的userServiceImpl类
dao层
第五步测试
我们现在要使用vue,mybatis,mysql实现一个简单的登录注册页面功能
使用的数据库:
create table user( id int primary key auto_increment, username varchar(10) not null , password varchar(20) not null ); insert into user values (null,'zhangsan','1234'),(null,'hema','134'),(null,'wangu','456');
第一步环境搭建
后端:
在idea创建web工程
创建成功
创建成功后把pom.xml文件中关于junit的依赖全部删除,我们不需要
接着在pom.xml中导入相关依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.hhh</groupId> <artifactId>web4_zhuce</artifactId> <version>1.0-SNAPSHOT</version> <name>web4_zhuce</name> <packaging>war</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.target>11</maven.compiler.target> <maven.compiler.source>11</maven.compiler.source> </properties> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <!-- mysql依赖 --> <!--mysql 驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency> <!--mybatis依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.1</version> </dependency> <!--添加slf4j日志api--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.20</version> </dependency> <!--logback-classic依赖--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <!--添加logback_core依赖--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.2</version> </plugin> </plugins> </build> </project>
接着在resource目录下创建mybatis-config.xml文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="jdbc.properties"> </properties> <environments default="development"> <!--设置默认的环境development,也可以配置多环境开发--> <environment id="development"> <transactionManager type="JDBC"/> <!--使用mybatis自带的连接池POOLED--> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <!--配置映射文件关联的参数--> <mappers> <!--扫描mapper--> <package name="com.hhh.dao"/> </mappers> </configuration>
创建jdbc.properties文件
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/day10 jdbc.username=root jdbc.password=123456
创建logback.xml文件
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径--> <property name="LOG_HOME" value="D:/log"/> <!-- 控制台输出 --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <!-- 日志输出编码 --> <Encoding>UTF-8</Encoding> <layout class="ch.qos.logback.classic.PatternLayout"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n </pattern> </layout> </appender> <!-- 按照每天生成日志文件 --> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <Encoding>UTF-8</Encoding> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--日志文件输出的文件名--> <FileNamePattern>hhh/mybatisTest.log.%d{yyyy-MM-dd}.log</FileNamePattern> <MaxHistory>30</MaxHistory> </rollingPolicy> <layout class="ch.qos.logback.classic.PatternLayout"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n </pattern> </layout> <!--日志文件最大的大小--> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">222 <MaxFileSize>1MB</MaxFileSize> </triggeringPolicy> </appender> <!-- 日志输出级别 --> <root level="ALL"> <!-- 注意:如果这里不配置关联打印位置,该位置将不会记录日志--> <appender-ref ref="CONSOLE"/> <appender-ref ref="FILE"/> </root> </configuration>
这样一来我们后端的环境搭建好了,我们可以启动一下,查看是否报错
然后我们在java目录中创建pojo包封装数据库表的类
在pojo包下创建出对应的类之后,把id的类型改成Long对象型
前端:
在vscode中创建vue工程
在终端命令中书写
vue init webpack work
生成完成
然后在package.json中导入axios依赖
npm install axios@^0.27.2
注意如果版本太高,npm run dev会报错
WAIT Compiling... 下午2:51:42 94% asset optimization ERROR Failed to compile with 2 errors 下午2:51:43 error in ./node_modules/axios/lib/platform/index.js Module parse failed: Unexpected token (5:2) You may need an appropriate loader to handle this file type. | | export default { | ...utils, | ...platform | } @ ./node_modules/axios/lib/defaults/index.js 8:0-44 @ ./node_modules/axios/lib/axios.js @ ./node_modules/axios/index.js @ ./src/main.js @ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/main.js error in ./node_modules/axios/lib/core/mergeConfig.js Module parse failed: Unexpected token (6:69) You may need an appropriate loader to handle this file type. | import AxiosHeaders from "./AxiosHeaders.js"; | | const headersToObject = (thing) => thing instanceof AxiosHeaders ? { ...thing } : thing; | | /** @ ./node_modules/axios/lib/axios.js 6:0-48 @ ./node_modules/axios/index.js @ ./src/main.js @ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/main.js
之后再vue文件中使用axios时,需要在<script></script> 中加上import axios from 'axios';
把前端的端口号改成8090,不然于tomcat服务器冲突
这样一来我们的环境已经搭建完成
第二步画流程图
实现登录功能
我们会在浏览器页面输入http://localhost:8090来访问前端服务器,接着前端服务器使用axios把从浏览器接收的数据发送给后端服务器(一次请求和响应),再tomcat服务器中使用三层架构模型(web,service,dao)
web:
- 解决post请求的中文乱码问题
- 接收来自前端提交的请求参数
- 将请求参数封装到User实体类-->user
- 创建业务层对象service对象
- 使用业务层对象调用业务层的登录方法(login)-->User u=userService.login(user)
- 判断u是否为null
- 如果u=null,说明没有查到用户,登陆失败,响应给前端一个false
- 如果u不为null,说明查到用户,登录成功,响应true
service:
- 定义登录方法接收web传递的user对象,并返回给web层一个新的对象
- 在登录方法中根据MybatisUtil工具类获取mybatis会话对象
- 使用会话对象调用方法获取dao层的接口代理对象
- 使用接口代理对象调用接口的登录方法(会返回一个User对象),user作为参数传递
- 释放资源
- 直接返回查询到的User对象
dao层:
- 创建接口
- 在接口中定义登录方法
- 在方法上使用注解查询数据
第三步前端代码的实现
这是开始的页面,接下来我们要到router路由下书写#login的路径
注意:在路由的路径不用写#
路由中的component在我们自己创建的views书写vue文件
login.vue代码
<template> <div id="app"> <!-- v-model与user的username属性双向绑定 --> <span id="err" style="display: none">用户名或者密码错误</span> <input type="text" name="username" v-model="user.username"> <br> //使用双向绑定把表单数据与data中的user的username绑定 <input type="password" name="password" v-model="user.password"> <br> <button @click="send">登录</button> </div> </template> <script> //导入axios import axios from 'axios'; export default { data() { return { user:{ username:'', password:'' }, }; }, methods: { send() { //后端服务器的路径 let url="http://localhost:8080/loginServlet"; let params=`username=${this.user.username}&password=${this.user.password}`; //使用重音符,进行字符串拼接请求参数 //使用axios的post请求,将服务器地址,请求参数 axios.post(url, params) .then(res => { //console.log(res.data); if(res.data){ location.href="#/success" //跳转到成功的页面 }else{ document.getElementById("err").style.display="block"; document.getElementById("err").style.color="red"; } }); // .catch(error => { // console.error(error); // }); } } } </script> <style> </style>
启动前端项目
可以发现username的数据已经与表单数据关联,注意username是data中的username
点击登录,并查看抓包
注意:抓包的username是 let params=`username=${this.user.username}&password=${this.user.password}`;
axios的请求参数左边的usernmae
后端使用request接收前端的数据就要使用username来获取
#/success的success.vue文件
#/register的register.vue文件
<template> <div id="app"> <!-- v-model与user的username属性双向绑定 --> <span id="err" style="display:none">该用已经存在,注册失败</span> <span id="su" style="display:none">注册成功</span> <input type="text" name="username" v-model="user.username"> <br> <input type="password" name="password" v-model="user.password"> <br> <button @click="send">注册</button> </div> </template> <script> import axios from 'axios'; export default { data() { return { user:{ username:'', password:'' }, }; }, methods: { send() { //在config-index.js中已经配置了服务器的三要素 let url="http://localhost:8080/registerServlet"; let params=`username=${this.user.username}&password=${this.user.password}`; axios.post(url, params) .then(res => { if(res.data){ document.getElementById("su").style.display="block"; document.getElementById("su").style.color="green"; //location.href="#/success"; }else{ document.getElementById("err").style.display="block"; document.getElementById("err").style.color="red"; } }) .catch(error => { console.error(error); }); } } } </script> <style> </style>
第四步:后端代码的实现
先实现 //后端服务器的路径
let url="http://localhost:8080/loginServlet";
web层loginServer类
@WebServlet("/loginServlet")//要与前端的axios路径一致 public class loginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //解决中文乱码问题 request.setCharacterEncoding("utf-8"); //接收前端提交的请求参数 String username = request.getParameter("username"); String password = request.getParameter("password"); //封装成对象 User user = new User(); user.setUsername(username); user.setPassword(password); //创建业务层service层对象 UserServiceImpl userService=new UserServiceImpl(); //使用业务层对象调用业务层的登录方法 User u=userService.login(user); //判断u是否为空 if(u==null) { response.addHeader( "Access-Control-Allow-Origin","*");//允许所有来源访同 response.addHeader( "Access-Control-Allow-Method","POST,GET");//允许访问的方式 //u为null,说明没有查到用户,登陆失败,响应给前端一个false response.getWriter().print(false); } else{ response.addHeader( "Access-Control-Allow-Origin","*");//允许所有来源访同 response.addHeader( "Access-Control-Allow-Method","POST,GET");//允许访问的方式 //n不为null,说明存在用户,登录成功,响应一个true response.getWriter().print(true);//会被axios的res对象的data接收 } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
response.addHeader( "Access-Control-Allow-Origin","*");//允许所有来源访同
response.addHeader( "Access-Control-Allow-Method","POST,GET");//允许访问的方式这两行十分重要,不然会报错:
Access to XMLHttpRequest at ‘http://localhost:8080/xxx’ from origin ‘http://localhost:63342’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
web层registerServlet类
@WebServlet("/registerServlet") public class registerServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //处理中文请求乱码问题 request.setCharacterEncoding("utf-8"); //接收参数 String password = request.getParameter("password"); String username = request.getParameter("username"); //封装成对象 User user = new User(); user.setUsername(username); user.setPassword(password); //创建业务层对象 UserServiceImpl userService = new UserServiceImpl(); //调用业务层对象的注册方法 boolean result=userService.register(user); //判断结果对错 if(result){ response.addHeader( "Access-Control-Allow-Origin","*");//允许所有来源访同 response.addHeader( "Access-Control-Allow-Method","POST,GET");//允许访问的方式 response.getWriter().print(true); }else{ response.addHeader( "Access-Control-Allow-Origin","*");//允许所有来源访同 response.addHeader( "Access-Control-Allow-Method","POST,GET");//允许访问的方式 response.getWriter().print(false); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
service的userServiceImpl类
public class UserServiceImpl { //定义登录方法 public User login(User user) { //获取MybatisUtil工具类 SqlSession sqlSession = MybatisUtil.openSession(); //使用会话对象调用方法获取dao层的接口代理对象 UserMapper mapper=sqlSession.getMapper(UserMapper.class); //使用接口代理对象调用方法 User u=mapper.login(user); //释放资源 MybatisUtil.closeSqlSession(sqlSession); //直接返回User对象 return u; } public boolean register(User user) { SqlSession sqlSession=null; try { //获取MybatisUtil工具类 sqlSession = MybatisUtil.openSession(); //使用会话对象调用方法或缺dao层的代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //使用接口代理对象调用方法 User u=userMapper.queryUserByUserName(user.getUsername()); //返回结果 if(u==null) { //没有改用户,可以注册 userMapper.register(user); //提交事务 sqlSession.commit(); //返回结果 return true; }else{ return false; } } finally { //防止空指针重复释放 if(sqlSession!=null){ //释放资源 MybatisUtil.closeSqlSession(sqlSession); } } } }
dao层
//创建接口 public interface UserMapper { //在接口中定义登录方法 //在方法使用注解 /* username=#{username} 左边的是数据库的字段名 右边是User类的成员变量 */ @Select("select * from user where username=#{username} and password=#{password}") User login(User user); @Insert("insert into user(username, password) values (#{username},#{password});") int register(User user); /* 关于mybatis入参: 1.如果方法只有一个非pojo Map类型参数,mybatis底层没有处理,我们在#{}中的获取数据可以随便写,所以建议 使用注解@Param("标识符")修饰参数,那么此时#{}的大括号只能书写@Param("标识符")的标识符 */ @Select("select * from user where username=#{username}") User queryUserByUserName(@Param("username") String username); }
第五步测试
注册功能
登录: