目标:
- 数据库连接
- 完成前端登录页面和注册的搭建
- 完成后端代码的编写,实现登录功能
后端登录代码实现
登录实现分析
- 用户在登录页面输入登录名和密码,提交请求给LoginServlet
- 在LoginServlet中接收请求和数据[用户名和密码]
- 在LoginServlt中通过Mybatis实现调用UserMapper来根据登录名和密码查询数据库表
- 将查询的结果封装到teacher对象中进行返回
- 在LoginServlet中判断返回的teacher对象是否为null
- 如果为nul,说明根据用户名和密码没有查询到用户,则登录失败,返回"登录失败"数据给前端
- 如果不为null,则说明用户存在并且密码正确,则登录成功,返回"登录成功"数据给前端
三层架构实现步骤:
【Dao层】:
在teacherMapper编写查询教师数据的sql语句
【Servlet层】:
调用 teacherMapper 实现sql查询教师信息,传递给web层
【web层】:
接收前台登录信息
调用Servlet层代码查询登录数据是否正确,返回teacher对象
查询结果作为提示通过session会话存储到服务器,返回给前端页面展示
一、项目连接数据库
1、MyBatis光网:https://mybatis.org/mybatis-3/zh/index.html
点击入门可以快速上手
2、项目maven坐标第一篇有已经完成所有的依赖坐标引入了
3、在resources
包下创建mybatis-config.xml
配置文件【连接数据库】
将有注释的代码靠考到当前创建的配置文件里面,并按需求修改数据库的连接方式
示例代码和创建文件截图
注意:官网的mappers标签里是,我这里改为了包扫描,到com.zcl.mapper
包,也是一样的
<?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>
<!--起别名-->
<typeAliases>
<package name="com.zcl.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--数据库注册驱动-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--连接的数据库-->
<property name="url" value="jdbc:///stagedb?useSSL=false&useServerPrepStmts=true"/>
<!--登录名-->
<property name="username" value="root"/>
<!--密码-->
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--<mapper resource="org/mybatis/example/BlogMapper.xml"/>-->
<package name="com.zcl.mapper"/>
</mappers>
</configuration>
4、在resources.com.zcl.mapper
包下创建sql映射文件【teacherMapper.xml
】
官网截图如下:
示例代码和插件推荐
注意:namespace
内的映射接口是com.zcl.mapper.teacherMapper
包下的teacherMapper接口,如下一段代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--teacherMapper.xml数据库映射文件是与teacherMapper接口对映的-->
<mapper namespace="com.zcl.mapper.teacherMapper">
<!--编写sql语句-->
</mapper>
5、在com.zcl.mapper.teacherMapper
包下创建与teacherMapper.xml
映射文件同名的接口
插件介绍:可以快速跳转映射文件和接口之间,创建成功之后会有一个小鸟的标识,点击可以跳过去,并可以生成对应的sql映射文件
说明:
teacherMapper.xml和teacherMapper接口
:是Dao层实现sql语句的
teacherMapper.java
:接口对于普通的sql查询语句可以使用注解来完成,复杂一点的需要到teacherMapper.xml
映射文件中去写,官网有介绍
关于映射文件的namespace
需要填写的是映射对应的接口,后台调用sql语句是从teacherMapper
接口中调用的
在util
包下创建SqlSessionFactoryUtils
工具类获取 SqlSession
package com.zcl.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class SqlSessionFactoryUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
//静态代码块会随着类的加载而自动执行,且只执行一次
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}
SqlSessionFactoryUtils工具类的作用:简化了代码重复和创建消耗
二、实现教师登录后端登录查询效果
1、查询教师登录信息
在pojo
包下创建Teacher
实体类用于查询返回数据
package com.zcl.pojo;
/**
* TODO:
*
* @author zcl
* @date 2022/4/2 8:41
*/
public class Teacher {
private int id;
private String teacherName;
private String password;
private int status;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTeacherName() {
return teacherName;
}
public void setTeacherName(String teacherName) {
this.teacherName = teacherName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
@Override
public String toString() {
return "Teacher{" +
"id=" + id +
", teacherName='" + teacherName + '\'' +
", password='" + password + '\'' +
", status=" + status +
'}';
}
}
在teacherMapper
接口上通过注解方式来查询教师信息,并返回Teacher
对象
package com.zcl.mapper;
import com.zcl.pojo.Teacher;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* TODO:
*
* @author zcl
* @date 2022/4/2 8:07
*/
public interface teacherMapper {
/**
* 查询教师登录信息
* @return
*/
@Select("select * from tb_teacher where teacherName = #{teacherName},password = #{password}")
Teacher querTeacher(@Param("teacherName") String teacherName, @Param("password") String password);
}
2、编写Service层代码
在service
包下创建teacherService
接口
里面写有teacherMapper
Dao层的同名代码
作用:通过接口可以简化在servlet包下创建多个类,在ipml包里面创建一个类实现这个接口就可以起到简化作用
package com.zcl.service;
import com.zcl.pojo.Teacher;
import java.util.List;
/**
* TODO:
*
* @author zcl
* @date 2022/4/2 9:07
*/
public interface teacherService {
/**
* 查询教师登录信息
* @return
*/
Teacher querTeacher(String teacherName,String password);
}
在ipml
包下创建teacherServicelmpl
类实现teacherService 接口并实现里面的方法
在实现的接口方法里面写具体的service层方法来调用Dao层代码
Service层的具体实现思路:
1、获取到SqlSessionFactory工厂对象,已经封装到了SqlSessionFactoryUtils
工具类里面
2、调用SqlSessionFactory获取到SqlSession
对象
3、通过SqlSession
对象获取到teacherMapper
对象就可以调用里面写的Dao层sql语句
4、获取到数据之后需要返回并释放资源
package com.zcl.service.impl;
import com.zcl.mapper.teacherMapper;
import com.zcl.pojo.Teacher;
import com.zcl.service.teacherService;
import com.zcl.util.SqlSessionFactoryUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.util.List;
/**
* TODO:
*
* @author zcl
* @date 2022/4/2 9:14
*/
public class teacherServicelmpl implements teacherService {
// 1、获取SqlSessionFactory工厂对象
SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
@Override
public Teacher querTeacher(String teacherName,String password) {
// 2、获取sqlSession对象
SqlSession sqlSession = factory.openSession();
// 3、获取teacherMapper对象
teacherMapper mapper = sqlSession.getMapper(teacherMapper.class);
// 4、调用方法【传递查询条件】
Teacher teachers = mapper.querTeacher(teacherName,password);
// 5、释放资源
sqlSession.close();
// 6、返回查询结果
return teachers;
}
}
com.zcl.webs.servlet
包下创建BaseServlet
并继承HttpServlet
接口,完成请求转发实现
作用:
不再需要根据注解的方式来访问控制器了,可以根据类名来访问,会更加的方便
package com.itheima.webs.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 1、替换HttpServlet,根据最好一段路径来进行方法分发
*
* @author zcl
* @date 2022/3/31 16:06
*/
public class BaseServlet extends HttpServlet {
/**
* 根据最好一段路径来进行方法分发
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求的路径
String uri = req.getRequestURI();
// 2、获取最好一段路径,方法名
int index = uri.lastIndexOf("/");
// selectAll
String methodName = uri.substring(index + 1);
// 3、执行方法
// 3.1、获取字节码对象
// this:谁调用代表谁
Class<? extends BaseServlet> cls = this.getClass();
// 3.2、获取方法 Method对象
try {
Method method = cls.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
// 3.3、执行方法
method.invoke(this,req,resp);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
com.zcl.webs.servlet
包下创建TeacherServlet
并实现BaseServlet
说明:
因为是上面创建了BaseServlet
可以直接访问类名来完成请求,就不再需要在方法上添加注解了
访问的路径可以写:服务器启动名称/test/类名
package com.zcl.webs.servlet;
import com.alibaba.fastjson.JSON;
import com.zcl.pojo.Teacher;
import com.zcl.service.impl.teacherServicelmpl;
import com.zcl.service.teacherService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
/**
* TODO:
*
* @author zcl
* @date 2022/4/2 11:12
*/
@WebServlet("/test/*")
public class TeacherServlet extends BaseServlet{
// 创建工厂模式
private teacherService teacherService = new teacherServicelmpl();
public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 接收页面数据
BufferedReader reader = request.getReader();
String str = reader.readLine();
// 将获取的数据转换为Teacher实体类
Teacher teacher1 = JSON.parseObject(str, Teacher.class);
System.out.println(teacher1);
/*String teacherName = request.getParameter("teacherName");
String password = request.getParameter("password");
System.out.println(teacherName);
System.out.println(password);*/
// 1、调用方法查询数据
Teacher teacher = teacherService.querTeacher(teacher1.getTeacherName(),teacher1.getPassword());
// 2、把对象转为JSON
// 3、写数据
response.setContentType("text/json;charset=utf-8");
PrintWriter writer = response.getWriter();
// 4、判断查询的结果是否为空
if(teacher != null){
writer.write("succeed");
//将登陆成功后的user对象,存储到session
HttpSession session = request.getSession();
session.setAttribute("teacher1",teacher);
}else {
writer.write("failure");
}
}
}
3、启动程序服务
需要添加了maven里的tomcat创建才会有的
点击控制台的连接
页面中输入请求控制器和请求参数【登录数据】
后端数据连接正常,接下来就是弄前端的登录和注册页面了
三、前后端相连接实现完整登录功能
前端页面搭建
效果展示
注册页面
复制登录注册模板文件到webapp文件中
需要模板文件的可以关注私信我发你,也可以自己搭建页面信息
页面传递信息请求
<script src="js/vue.js"></script>
<script src="element-ui/lib/index.js"></script>
<script src="js/axios-0.18.0.js"></script>
<script>
$("#btnSub").click(function () {
var teacherName = $("#teacherName").val();
var paw2 = $("#paw2").val();
// json对象
var jsObject = {teacherName:teacherName,password:paw2};
axios({
method:"post",
url:"http://localhost:8080/JavaWebUltimateDemo/test/login",
data:jsObject //这里 axios 会将该js对象转换为 json 串的
}).then(function (resp) {
if(resp.data == "succeed"){
window.location.href = "http://localhost:8080/JavaWebUltimateDemo/brand.html";
}else if(resp.data == "failure"){
alert("请检查登录信息是否正确")
};
})
});
</script>
请求页面之后会跳转如下页面
后面查询数据绑定上来即可
登录拦截
问题引入:
当我们根据绝对路径访问内容的时候一样会呈现出我们需要看到的内容,这样是很不安全的,在没有登录的情况下也可以看到需要权限的内容也是很不合理,所以我们通过Filter
拦截需要加入登录权限的方法,具体实现步骤参考如下实现步骤:
1、创建com.zcl.webs.filter
包,存放拦截过滤器
2、创建FilterDemo
类,需要实现Filter
接口,注意导包是如下的包,不要导错了
import javax.servlet.annotation.WebFilter;
3、实现接口的所有接口
/*代表拦截所有的请求
拦截了就得设置放行代码,不然前端页面会访问不到页面数据
package com.zcl.webs.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*")
public class FilterDemo implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("FilterDemo...");
//放行
chain.doFilter(request,response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/**
* 销毁执行的方法
*/
@Override
public void destroy() {
}
}
登录实现步骤
- 获取Session对象
- 从Session对象中获取名为
user
的数据 - 判断获取到的数据是否是 null
- 如果不是,说明已经登陆,放行
- 如果是,说明尚未登陆,将提示信息存储到域对象中并跳转到登陆页面
自述:
这一篇总结写的不是很好,全程没有状态,停留了几天才完成更加的不知道怎么接上和描述
知识点也有忘记,基础不是很扎实
希望下一篇写的会更好一些
如果阅读过程中有什么不懂的可以评论私信问一下