上一篇教程和大家一起整合了Spring+SpringMVC+MyBatis+Shiro+Log4j框架,我们在学习java web编程道路上都会遇到几个坎,迈过去了就一路欢畅,很多没迈过去的同学就放弃了。第一个坎是安装集成开发环境,第二个坎就是各个框架的整合。同学们如果能解决整合过程中遇到的各种各样的问题并完成整合,那基本上可以说已经入了门,向web编程迈进了一大步!
本篇教程呢,和大家开始实现后台管理系统页面和相关功能,第一个要实现的功能就是登录。在这里,为了能让大家更加深刻地体会工作中的实际开发流程,我们来模拟实际开发中以需求驱动的形式来完成这篇教程的讲解。
一、登录功能的需求
首先我们来理清一下完整的登录功能有哪些需要实现的功能点,一个完整的登录功能应该包括:
- 登录页面实现(login.jsp):包含用户名和密码输入框,一个“登录”按钮
- 账号信息验证成功后,跳转到系统首页(index.jsp)
- 当登录失败时,提示失败信息,如“用户名或密码错误”、“用户已锁定”等
二、登录页面实现
1. login.jsp。页面中两个输入框,一个登录按钮。并且,用户名输入框上方有个默认隐藏的span,用于展示错误信息。点击【登录】按钮调用login()方法向后台发起Ajax请求,当登录不成功时,提示后台返回的错误信息;登录成功时,跳转到"/index"页面。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path;
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<title>欢迎登录OMS</title>
<link rel="stylesheet" href="<%=basePath%>/css/bootstrap-3.3.7-dist/css/bootstrap.min.css">
<link rel="stylesheet" href="<%=basePath%>/css/font-awesome-4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="<%=basePath%>/css/login.css">
<script type="text/javascript" src="<%=basePath%>/js/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="<%=basePath%>/css/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
<style>
#login_logo {
background-image: url(<%=basePath%>/image/login/login_logo.png);
background-repeat: no-repeat;
background-position: center
}
#login_page_img {
background-image: url("<%=basePath%>/image/login/login-img.png");
width: 500px;
height: 440px;
}
#username, #password, #vcode {
width: 100%;
height: 38px;
align-items: self-end;
}
</style>
<script type="text/javascript">
function login() {
console.log('login ------> start');
var username = $('#username').val();
var password = $('#password').val();
//判断输入是否为空
if (username == '' || password == '') {
alert('账号信息不能为空!');
return;
}
$.ajax({
type: 'post',
url: '<%=basePath%>/user/checkLogin',
cache: false,
dataType: 'json',
data: {username: username, password: password},
success: function (data) {
if (data.code == '0') {
window.location.href = '<%=basePath%>/index';
} else {
console.log(data.msg);
$("#tips").css("visibility", "visible");
$('#tips').text(data.msg);
}
},
error: function (data) {
alert('登录失败,请联系系统管理员');
}
})
}
</script>
</head>
<body>
<div class="login_box">
<div class="login_l_img" id="login_page_img"></div>
<div class="login">
<div class="login_logo" id="login_logo"></div>
<div class="login_name">
<p style="margin: 0px">欢迎登录</p>
</div>
<table style="width: 100%; vertical-align: middle">
<tr>
<td colspan="2"><span id="tips" style="color: red; visibility: hidden"> </span></td>
</tr>
<tr style="width: 100%">
<td colspan="2">
<div class="input-group" style="margin-bottom: 15px;width: 100%">
<span class="input-group-addon" id="basic-addon1">
<i class="glyphicon glyphicon-user"></i>
</span>
<input class="form-control" name="username" id="username" type="text" placeholder="请输入用户名" οninput="value=value.replace(/[^a-zA-Z0-9]+$/,'');if(value.length>20)value=value.slice(0,20)">
</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="input-group" style="margin-bottom: 15px;width: 100%">
<span class="input-group-addon" id="basic-addon-pwd">
<i class="glyphicon glyphicon-lock"></i>
</span>
<input class="form-control" name="password" id="password" type="password" placeholder="请输入密码" οninput="value=value.replace(/[^a-zA-Z0-9~!@#$%^&*()_+.?]+$/,'');if(value.length>20)value=value.slice(0,20)">
</div>
</td>
</tr>
<tr>
<td colspan="2"><a class="btn btn-info" style="width:100%;" οnclick="login()">登录</a></td>
</tr>
</table>
</div>
<div class="copyright">小云科技有限公司 版权所有©2016-2019 技术支持电话:000-00000000</div>
</div>
<div style="text-align:center;display:none">
<input id="code" type="hidden" value="${code}">
<input id="msg" type="hidden" value="${msg}">
</div>
<script>
$(function () {
//按回车触发登录
$(".login").keypress(function (e) {
var code = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
if (13 == code) {
//回车键
login();
}
});
});
</script>
</body>
</html>
2. index.jsp。index页面没加什么内容,只展示后台返回的${current_user}和${page}变量。
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path;
%>
<html>
<body>
<h2>index.jsp</h2>
<h3>当前登录用户:${current_user}</h3>
<h3>当前页面:${page}</h3>
</body>
</html>
三、后台请求处理和控制跳转
1. MainPageController.java。用于处理"/login"和"/index"请求,相当于指定页面进行跳转。
package com.ssm.controller;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
public class MainPageController {
private static final String LOGIN_PAGE = "login";
private static final String INDEX_PAGE = "index";
private static Logger logger = Logger.getLogger(MainPageController.class);
@RequestMapping("/login")
public ModelAndView login() {
ModelAndView model = new ModelAndView(LOGIN_PAGE);
model.addObject("page", "login.jsp page's value");
return model;
}
@RequestMapping("/index")
public ModelAndView index(HttpServletRequest request, HttpServletResponse response) {
ModelAndView model = new ModelAndView(INDEX_PAGE);
String username = request.getSession().getAttribute("username").toString();
model.addObject("page", "index.jsp page");
model.addObject("current_user", username);
return model;
}
}
2. UserControlller.java。处理login.jsp中login()方法中的"/checkLogin"请求,进行登录校验,并返回校验结果和提示信息。
package com.ssm.controller;
import com.ssm.model.ResultObj;
import com.ssm.model.User;
import com.ssm.service.IUserService;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
@RequestMapping("/user")
public class UserController {
private static Logger logger = Logger.getLogger(UserController.class);
@Resource
private IUserService userService;
@RequestMapping(value = "/getUserByUsername/{username}", method = RequestMethod.GET)
public ModelAndView getUserByUsername(@PathVariable("username") String username, HttpServletRequest request, HttpServletResponse response) {
User user = userService.getUserByUsername(username);
logger.info("userId: " + user.getId() + ", username: " + user.getUsername() + ", cname: " + user.getCname());
ModelAndView model = new ModelAndView("user");
model.addObject("user", user);
return model;
}
@ResponseBody
@RequestMapping(value = "/checkLogin", method = RequestMethod.POST)
public ResultObj checkLogin(HttpServletRequest request, HttpServletResponse response) {
logger.info("/user/checkLogin ---> start");
String username = request.getParameter("username");
String password = request.getParameter("password");
//验证登录信息
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Subject currentUser = SecurityUtils.getSubject();
ResultObj result = new ResultObj();
try {
currentUser.login(token);
result.setCode("0");
result.setMsg("登录成功");
logger.info("登录成功");
request.getSession().setAttribute("username", username);
} catch (UnknownAccountException uae) {
logger.error("用户名错误" + uae.getMessage());
result.setCode("1");
result.setMsg("用户名错误");
} catch (IncorrectCredentialsException ice) {
logger.error("密码错误" + ice.getMessage());
result.setCode("2");
result.setMsg("密码错误");
} catch (LockedAccountException lae) {
logger.error("账号锁定" + lae.getMessage());
result.setCode("3");
result.setMsg("账号已锁定,请联系系统管理员解锁");
}
logger.info("/user/checkLogin ---> end");
return result;
}
}
四、本篇结束语
login.jsp中使用了Bootstrap、jQuery、图片等静态资源,同学们可以根据资源文件名自行网上下载,也欢迎加群获取?:584017112