文章目录
登录功能
1、登录功能分析
2、基础代码编写
- User.java(src\main\java\domain\User.java)
public class User {
private int uid;
private String username;
private String password;
private Date birthday;
private String name;
private String sex;
private String telephone;
private String email;
private char status;
private String code;
}
- TestUserService测试类(src\test\java\service\TestUserService.java)
//测试
public class TestUserService {
@Test
public void test01() {
//将用户输入账号与密码发到后台
UserService userService = new UserService();
//1:查找用户数据
User user = userService.findUserByName("jackhello");
//2:根据数据, 正确,错误,不存在。
if (user == null) {
System.out.println("不存在");
} else {
//1:3种情况
System.out.println("存在");
}
}
@Test
public void test02() {
//将用户输入账号与密码发到后台
UserService userService = new UserService();
//1:查找用户数据
User user = new User();
user.setUsername("jackhello");
user.setPassword("123456");
user.setStatus('Y');
int code = userService.login(user);
//2:根据数据, 正确,错误,不存在。
System.out.println(code);
}
}
- 编写UserDao方法(src\main\java\dao\UserDao.java)
public interface UserDao {
//select * from tab_user where username = 'jackhello'
User findByName(String name);
}
- UserDao测试(src\test\java\dao\UserDaoTest.java)
public class UserDaoTest {
// @Before:用来初始化@Test方法要使用到的资源
// @After:用来释放资源
// @Before ->@Test -> @After
private SqlSession session;
private UserDao userDao;
@Before
public void init() throws Exception {
System.out.println("Before");
//创建Session对象
session = MySessionUtils.getSession();
userDao = session.getMapper(UserDao.class);
}
@After
public void destory() throws Exception {
System.out.println("After");
//提交与关闭session
session.commit();
session.close();
}
@Test
public void test01() {
//查找对象
User user = userDao.findByName("jackhello");
//查看对象
System.out.println(user);
}
@Test
public void test02() {
User user = userDao.findByName("jackhello");
//查看对象
System.out.println(user);
}
}
- UderDao.xml
<mapper namespace="com.smp.dao.UserDao">
<select id="findByName" parameterType="string" resultType="user">
select * from tab_user where username = #{
username}
</select>
</mapper>
- SalMapConfig.xml
<configuration>
<typeAliases>
<package name="com.smp.domain"/>
</typeAliases>
<environments default="mybatis">
<environment id="mybatis">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- 四大信息 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/lvyou?characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 一个mapper标签可以指定一个映射文件-->
<mappers>
<mapper resource="UserDao.xml"/>
</mappers>
</configuration>
- UserService的login方法
public class UserService {
//直接获取Dao
public User findUserByName(String name) {
//getMapper是mybatis,给接口生成实现类,将实现类对象返回
UserDao userDao = MySessionUtils2.getSession().getMapper(UserDao.class);
//根据用户名查找用户
User user = userDao.findByName(name);
MySessionUtils2.getSession().commit();
return user;
}
public int login(User user) {
//账号密码
UserDao userDao = MySessionUtils2.getSession().getMapper(UserDao.class);
User u = userDao.findByName(user.getUsername());
//比对数据库的账号密码
if (u == null) {
return -1;//找不到jack
} else {
//判断是否是激活的账户
if ('Y'== u.getStatus()) {
//是激活用户
if (u.getUsername().equals(user.getUsername()) && u.getPassword().equals(user.getPassword())) {
return 1;//提示登录成功
} else {
return -2;//账号或者密码出错
}
} else {
return -3;//已激活
}
}
}
}
3、ThreadLocal介绍
- (1)在实际开发中,SqlSession属于Dao层代码,不允许出现在Service层中
删除Mybastis依赖 - (2)ThreadLocal是什么?
java.lang.ThreadLocal 该类提供了线程局部 (thread-local) 变量,用于在当前线程中共享数据。 - (3)有什么特点?
》1 ThreadLocal工具类底层就是一个Map,key存放的当前线程,value存放需要共享的数据。
》2 使用哪个线程存的,就只能使用哪个线程取
ThreadLocal改造MySessionUtils
(src\main\java\util\MySessionUtils2.java)
public class MySessionUtils2 {
private static SqlSessionFactory sessionFactory;
//static 静态代码,在类加载的时候执行一次,且只执行一次
static{
// 》1 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 》2 创建SqlSessionFactory对象
InputStream inputStream = MySessionUtils2.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml");
sessionFactory = sqlSessionFactoryBuilder.build(inputStream);//加载核心配置文件 参1 输入流
// 》3 加载SqlMapConfig.xml配置文件
}
//A: 定义一个ThreadLocal集合,本质是Map<Thread,Object> map
private static ThreadLocal<SqlSession> map = new ThreadLocal<SqlSession>();
public static SqlSession getSession() {
//查找在local中,是否有对应的SqlSession
SqlSession sqlSession = map.get(); //map.get(Thread.currentThread())
if (sqlSession != null) {
//有就直接返回给调用者使用
return sqlSession;
} else {
//没有就创建一个新的,并且保存在local
sqlSession = sessionFactory.openSession();
//保存
map.set(sqlSession);
return sqlSession;
}
}
public static void commitAndClose() {
//将来进行写操作,之后需要提交,我们定义的方法
SqlSession session = map.get();
if (session != null) {
session.commit();//提交
session.close();//释放
//已经关闭的session不能留在local
//所以要删除
map.remove();
}
}
public static void rollbackAndClose() {
//将来进行写操作,之后需要提交,我们定义的方法
SqlSession session = map.get();
if (session != null) {
session.rollback();//回滚
session.close();//释放
//已经关闭的session不能留在local
//所以要删除
map.remove();
}
}
}
4、登录前台-表单校验1
- (1)校验用户名 /^\w{8,20}$/ 单词字符,长度8到20位
- (2)校验密码 /^\w{8,20}$/ 单词字符,长度8到20位
- (3)校验密码邮箱 = /^\w+@\w+.\w+$/ 邮箱 [email protected]
- 正则表达式
正则表达式.test(字符串)
返回一个布尔值
true 格式正确
false 格式错误
- login.jsp
<script type="text/javascript" >
function checkUserName(){
//获取输入框的值
var username = $("#username").val();
//正则表达式 定义一个规则,执行test方法,符合规则返回true,否则返回false
var reg = /^\w{
8,20}$/ ;
var flag = reg.test(username); //判断
//如果符合要求,设置输入框边框是正常,否则设置红色
if(flag){
$("#username").css("border","");
}else{
$("#username").css("border","1px solid red");
}
//alert(flag)
return flag;
}
function checkPassword(){
//判断密码输入框的值是否合法
var username = $("#password").val();
var reg = /^\w{
8,20}$/ ;
var flag = reg.test(username); //判断
if(flag){
$("#password").css("border","");//无色框
}else{
$("#password").css("border","1px solid red");//红框
}
//alert(flag)
return flag;
}
})
</script>
5、登录前台-表单校验2
- submit函数
控制表单是否提交,函数返回true,表单提交,返回false表单不提交
此处
在ajax提交,则写false
页面是一个带有submit按钮的form表单 ,可以拦截
使用jquery编写 ajax请求
- login.jsp
$("#btn_login").click(function () {
//要求两个值正确,我们才做提交
if(checkUserName()&&checkPassword()){
var un = $("#username").val()
var pw = $("#password").val()
//alert(un+pw)
//写提交
$.ajax({
url:"loginServlet",
async:true,
data:"username="+un+"&password="+pw,
type:"post",
dataType:"json",
success:function (data) {
// alert(data) {"code":1,"data":"登录成功"}
if(1 == data.code){
//跳转到主页 index.html
$("#errorMsg").html("");
window.location="index.html"
}else{
//显示在界面上
$("#errorMsg").html(data.data);
}
},
error:function () {
alert("服务器发生了错误")
}
});
}
6、登录后台_Servlet代码实现
-
(1)Servlet只做三件事
》接收请求获取参数
》处理参数
》将结果响应给浏览器 -
LoginServlet.java
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求参数
Map<String, String[]> map = request.getParameterMap();
User u = new User();
try {
//参1 javaBean 参2 map
BeanUtils.populate(u,map);//将map里面所有的参数赋值给javaBean
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//处理参数
UserService userService = new UserService();
int code = userService.login(u);
//响应给浏览器 ajax 是响应json给浏览器就可以
ResponseInfo info = new ResponseInfo();
info.setCode(code);
if(code == - 1){
info.setData("用户不存在");
}else if(code == 1){
info.setData("登录成功");
}else if(code == -2){
info.setData("账号密码出错");
}else if(code == -3){
info.setData("账号未激活");
}
//转成json
String json =new ObjectMapper().writeValueAsString(info);
response.getWriter().println(json);
}
}
7、过滤器
防止中文出现乱码
(src\main\java\web\filter\CharchaterFilter.java)
@WebFilter("/*")
public class CharchaterFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse rep, FilterChain filterChain) throws IOException, ServletException {
req.setCharacterEncoding("utf-8");
// 处理响应乱码
rep.setContentType("text/html;charset=utf-8");
// 放行请求
filterChain.doFilter(req,rep);
}
public void destroy() {
}
}
8、改进登录功能
(1)MySessionUtils改进
- A依赖B,移除B,A报错,耦合
(com\wzx\util\MySessionUtils2.java)
public static <T> T getMapper(Class clz) {
return (T) getSession().getMapper(clz);
}
- include标签
include指令 include指令用于在本JSP中引入其他JSP页面。
<%@ include file="relativeURI"%>
<jsp:include page="header.jsp"/>
<!--引入尾部-->
<div id="footer">
<%@include file="footer.jsp"%>
</div>
9、登录_欢迎信息提示
- LoginServlet.java(src\main\java\web)
if(code == 1){
info.setData("登录成功");
//查找出用户数据
User user = userService.findUserByName(u.getUsername());
//保存到session中
request.getSession().setAttribute("user",user);
- header.jsp
<!-- 登录状态 -->
<div class="login">
<%-- 将session中的用户数据取出来 --%>
<%-- 判断用户对象是否为空 如果是提示请登录,否则显示用户信息--%>
<c:if test="${user != null}">
<span>欢迎回来,${
user.name}</span>
</c:if>
<c:if test="${user == null}">
<span>您未登录,请登录</span>
</c:if>
<a href="myfavorite.html" class="collection">我的收藏</a>
<a href="${pageContext.request.contextPath}/loginOutServlet">退出</a>
</div>
10、退出功能
- header.jsp
<a href="${pageContext.request.contextPath}/loginOutServlet">退出</a>
- LoginOutServlet.java(src\main\java\web)
@WebServlet("/loginOutServlet")
public class LoginOutServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//查找session
HttpSession session = request.getSession();
//让session销毁或者过期
session.invalidate();
//重定向 login.jsp
response.sendRedirect(request.getContextPath()+"/login.jsp");
}
}
11、验证码功能
-
验证码流程
后台程序ASevlet产生随机字符 code1
随机字符保存在session中 code1
随机字符再转成图片响应给img标签
当用户提交表单时也同时提交输入的验证码 code2
后台程序B比较两个随机字符串是否相等,不相等则验证码出错。 -
login.jsp
<div class="verify">
<input name="check" type="text" placeholder="请输入验证码" autocomplete="off">
<span><img src="checkCode" alt="" onclick="changeCheckCode(this)"></span>
<script type="text/javascript">
//图片点击事件
function changeCheckCode(img) {
img.src="checkCode?"+new Date().getTime();
}
</script>
- LoginServlet.java((src\main\java\web)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//从请求中获取check1码
String check1 = request.getParameter("check");
//从session中获取check2码
String check2 = (String) request.getSession().getAttribute("CHECKCODE_SERVER");
System.out.println(check1);
System.out.println(check2);
//从session中删除check2码
request.getSession().removeAttribute("CHECKCODE_SERVER");
//比较check1 与 check2
//相同表示验证码不正确,将提示信息写到页面的错误提示
if(check1 == null || !check1.equalsIgnoreCase(check2)){
//验证码不看大小写
ResponseInfo responseInfo = new ResponseInfo();
responseInfo.setCode(-4);
responseInfo.setData("登录失败,验证码出错");
//json
String json = new ObjectMapper().writeValueAsString(responseInfo);
response.getWriter().println(json);
return;
}
- CheckCodeServlet.java((src\main\java\web)
@WebServlet("/checkCode")
public class CheckCodeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
//服务器通知浏览器不要缓存
response.setHeader("pragma","no-cache");
response.setHeader("cache-control","no-cache");
response.setHeader("expires","0");
//在内存中创建一个长80,宽30的图片,默认黑色背景
//参数一:长
//参数二:宽
//参数三:颜色
int width = 80;
int height = 30;
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//获取画笔
Graphics g = image.getGraphics();
//设置画笔颜色为灰色
g.setColor(Color.GRAY);
//填充图片
g.fillRect(0,0, width,height);
//产生4个随机验证码,12Ey
String checkCode = getCheckCode();
//将验证码放入HttpSession中
request.getSession().setAttribute("CHECKCODE_SERVER",checkCode);
//设置画笔颜色为黄色
g.setColor(Color.YELLOW);
//设置字体的小大
g.setFont(new Font("黑体",Font.BOLD,24));
//向图片上写入验证码
g.drawString(checkCode,15,25);
//将内存中的图片输出到浏览器
//参数一:图片对象
//参数二:图片的格式,如PNG,JPG,GIF
//参数三:图片输出到哪里去
ImageIO.write(image,"PNG",response.getOutputStream());
}
/**
* 产生4位随机字符串
*/
private String getCheckCode() {
String base = "0123456789ABCDEFGabcdefg";
int size = base.length();
Random r = new Random();
StringBuffer sb = new StringBuffer();
for(int i=1;i<=4;i++){
//产生0到size-1的随机值
int index = r.nextInt(size);
//在base字符串中获取下标为index的字符
char c = base.charAt(index);
//将c放入到StringBuffer中去
sb.append(c);
}
return sb.toString();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}