酒业公司网站模板,wordpress nofollow,长沙做彩票网站公司,建立网站定制九 登录登出
1 登录作用 判断员工是否有权限访问#xff0c;首先得知道现在操作的人是谁#xff0c;所以必须先实现登录功能
2 登录流程 ① 提供登录页面#xff0c;可输入用户名与密码信息#xff0c;并添加执行登录的按钮。#xff08;登录页面不能被拦截#xff09;…九 登录登出
1 登录作用 判断员工是否有权限访问首先得知道现在操作的人是谁所以必须先实现登录功能
2 登录流程 ① 提供登录页面可输入用户名与密码信息并添加执行登录的按钮。登录页面不能被拦截 ② 给按钮绑定点击事件异步操作POST请求 ③ 事件中发送登录请求使用 AJAX 方式提交。使用 AJAX 原因用户体验更好既可保留用户刚输入的用户名和密码失败之后也不需要做请求转发共享错误信息直接返回 JSON 数据效率更高。 ④ 后端接收参数后查询数据库验证是否正确若登录失败则返回错误信息给前端若登录成功则把员工存到 session 中方便下次获取。 ⑤ 页面菜单栏显示登录员工的名字可以从 session 获取获取。
3 代码实现 ① 登录页面
!DOCTYPE html
html
headmeta charsetutf-8meta http-equivX-UA-Compatible contentIEedgetitleTJ管理平台-登录/titlelink relstylesheet href/static/js/bootstrap/css/bootstrap.csslink relstylesheet href/static/js/font-awesome/css/font-awesome.min.csslink relstylesheet href/static/js/Ionicons/css/ionicons.min.csslink relstylesheet href/static/js/adminlte/css/AdminLTE.min.csslink relstylesheet href/static/js/adminlte/css/skins/_all-skins.min.csslink relstylesheet href/static/js/adminlte/css/fonts.googleapis.com.cssscript src/static/js/jquery/jquery.min.js/scriptscript src/static/js/bootstrap/js/bootstrap.js/scriptscript src/static/js/adminlte/js/adminlte.min.js/scriptlink relstylesheet href/static/js/plugins/sweetalert2/sweetalert2.min.cssscript src/static/js/plugins/sweetalert2/sweetalert2.min.js/script/head
body classhold-transition login-page
div classlogin-boxdiv classlogin-logoa hrefhttp://www.tj.combplay/bTJ管理平台/a/divdiv classlogin-box-bodyp classlogin-box-msg请输入账号密码/pform methodpost idloginFormdiv classform-group has-feedbackinput typetext classform-control placeholder请输入账号 nameusername valueadminspan classglyphicon glyphicon-envelope form-control-feedback/span/divdiv classform-group has-feedbackinput typepassword classform-control placeholder请输入密码 namepassword value1span classglyphicon glyphicon-lock form-control-feedback/span/divdiv classrowdiv classcol-xs-4button typebutton classbtn btn-primary btn-block btn-flat submitBtn登录/button/div/div/form/divscript$(.submitBtn).click(function () {$.post(/*访问页面*//login,$(#loginForm).serialize(),/*表单序列化*/function (data) {if(data.success){// 登录成功location.href/employee/list} else{// 登录失败Swal.fire({text: data.msg,icon:error,});}})})/script
/div
/body
/html② 登录Controller
Controller
public class LoginController {Autowiredprivate IEmployeeService employeeService;Autowiredprivate IPermissionService permissionService;// 定义session对象将用户存入sessionRequestMapping(/login)ResponseBodypublic JsonResult login(String username, String password, HttpSession session){try {// 登录成功 根据用户名密码进行查询 此处 employee 一定不为空Employee employee employeeService.getByUsernameAndPassword(username,password);// session.setAttribute(UserContext.USER_IN_SESSION,employee);// 将当前用户存入线程UserContext.setCurrentUser(employee);// 获取当前用户的权限列表。ListString permissionList permissionService.queryByEmployeeId(employee.getId());// 将用户权限列表存入session// session.setAttribute(UserContext.PERMISSION_IN_SESSION,permissionList);UserContext.setPermission(permissionList);return new JsonResult(true,登录成功);} catch (Exception e){// 登录失败 打印失败信息e.printStackTrace();return new JsonResult(false,e.getMessage());}}RequestMapping(/logout)public String logout(HttpSession session){// session.invalidate();session.removeAttribute(user_in_session);return redirect:/static/login.html;}
}③ IEmployeeService
public interface IEmployeeService {//略/*** 根据用户名密码进行登录* param username* param password* return*/Employee getByUsernameAndPassword(String username, String password);
}④ EmployeeServiceImpl
Service
public class EmployeeServiceImpl implements IEmployeeService {Autowiredprivate EmployeeMapper employeeMapper;// 略Overridepublic Employee getByUsernameAndPassword(String username, String password) {// 基于性能优化填写的代码 防止传空if(!StringUtil.isNotEmpty(username) || !StringUtil.isNotEmpty(password)){throw new RuntimeException(账号密码有误);}Employee employee employeeMapper.getByUsernameAndPassword(username,password);if(employee null){// throw 有 return 的功能throw new RuntimeException(账号密码有误);}return employee;}
}⑤ 判空工具
public class StringUtil {public static boolean isNotEmpty(String str){return str ! null !str.trim().equals();}// 可在此处创建主方法对其进行测试
}⑥ EmployeeMapper
Repository
public interface EmployeeMapper {// 略Employee getByUsernameAndPassword(Param(username) String username, Param(password) String password);
}⑦ EmployeeMapper.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecn.tj.mapper.EmployeeMapper
!-- MyBatis 框架中用于定义如何从数据库结果集ResultSet映射到 Java 对象的标签--resultMap idBaseResultMap typecn.tj.domain.Employee id columnid propertyid /!--column为数据库中的列property是Java对象中的属性--result columnusername propertyusername /result columnname propertyname /result columnpassword propertypassword /result columnemail propertyemail /result columnage propertyage /result columnadmin propertyadmin /!--association 这个标签用于处理一对一或一对多的关联关系--association columnPrefixd_ propertydept javaTypedepartmentresult columnid propertyid /result columnname propertyname /result columnsn propertysn //association/resultMapselect idgetByUsernameAndPassword resultMapBaseResultMapselect e.id, e.username, e.name, e.password, e.email, e.age, e.admin,d.id d_id,d.name d_name,d.sn d_snfrom employee e left join department d on e.dept_id d.idwhere username#{username} and password#{password}/select
/mapper4 LoginController – 登出
Controller
public class LoginController {Autowiredprivate IEmployeeService employeeService;Autowiredprivate IPermissionService permissionService;// 略RequestMapping(/logout)public String logout(HttpSession session){// session.invalidate(); 杀掉Session session.removeAttribute(user_in_session); // 只移除session中对应的信息return redirect:/static/login.html;}
}5 登录拦截 实现步骤 ① 创建登录拦截器类实现前置拦截方法。 ② 判断 session 中是否有员工对象若有则代表有登录直接放行若没有则重定向到登录页面不放行。 ③ 在配置类中注册拦截器注意需要排除某些资源就是不需要登录都能访问的资源。 ④ 登录拦截器
Component
public class LoginInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 获取 Session 中的登录用户Employee employee UserContext.getCurrentUser();// 判断该用户是否存在if(employee null){// 没有登录提回登录页面response.sendRedirect(/static/login.html);return false;}return true;}
}⑤ 登录拦截器注册
Configuration
public class MvcJavaConfig implements WebMvcConfigurer {Autowiredprivate LoginInterceptor loginInterceptor;Overridepublic void addInterceptors(InterceptorRegistry registry) {// 所有需要注册的拦截器都封装到了 InterceptorRegistry 中。registry.addInterceptor(loginInterceptor) // 使用哪个拦截器(注册拦截器).addPathPatterns(/**) // 需要拦截的路径.excludePathPatterns(/static/**,/login); // 需要排除的路径 login为登录的处理器方法}
}6 权限拦截 ① 拦截流程 ② 权限拦截器
Component
public class PermissionInterceptor implements HandlerInterceptor{Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {/*** Object handler 就是我们需要访问的目标方法* 之所以是 Object 类型是因为方法有两种* 情况一访问静态资源 -- ResourceHttpRequestHandler* 情况二访问控制器方法 -- HandlerMethod*/// System.out.println(访问地址: request.getRequestURI() --- handler.getClass());// 获取当前登录用户。// Employee currentUser (Employee) request.getSession().getAttribute(user_in_session);Employee currentUser UserContext.getCurrentUser();//取出当前用户// 判断是否为超级管理员。if(currentUser.isAdmin()){//若为超级管理员则直接放行。return true;}// 判断是否为对应的类型if(handler instanceof HandlerMethod){// 拦截请求请求所对应的控制器方法。HandlerMethod method (HandlerMethod) handler;// 判断当前访问方法是否需要权限控制方法上是否有贴我们的自定义注解 RequirePermissionRequirePermission rpAnnotation method.getMethodAnnotation(RequirePermission.class);if(rpAnnotation null){// 如果没有注解说明是公共方法则直接放行。return true;}// 若有注解获取到注解的 expression 。//拦截器可以直接使用spring容器中的beanString expression rpAnnotation.expression();// 通过用户名获取当前用户的权限列表。// 用户登录后权限一般不会变不需要每进一个方法查询一次权限查询一次即可登录时获取并存入sessionListString permissionList UserContext.getPermission();// 判断当前拿到的 expression 在用户的权限列表中是否存在。if(!permissionList.contains(expression)){//permissionList中是否有expression// 根据请求的不同那么我们要返回时就需要碰到两种情况if(method.hasMethodAnnotation(ResponseBody.class)){// ajax 请求response.setContentType(application/json;charsetutf-8);response.getWriter().write(new ObjectMapper().writeValueAsString(new JsonResult(false,您还没有权限操作)));} else{// 页面请求templates文件夹相当于web中的inf文件夹 跳转控制器方法// 若不存在则说明当前登录用户没有该方法的访问权限。拦截请求。并提到没有权限的页面。// 该页面在templates中受保护不能直接从前端页面进行访问需要通过控制器进行中转response.sendRedirect(/permission/nopermission);}// 拦截return false;}}return true;}
}③ 注册权限拦截器
Configuration
public class MvcJavaConfig implements WebMvcConfigurer {Autowiredprivate LoginInterceptor loginInterceptor;Autowiredprivate PermissionInterceptor permissionInterceptor;Overridepublic void addInterceptors(InterceptorRegistry registry) {// 略// 权限拦截器registry.addInterceptor(permissionInterceptor) // 使用哪个拦截器(注册拦截器).addPathPatterns(/**) // 需要拦截的路径.excludePathPatterns(/static/**,/login,favicon.ico);}
}④ PermissionController 方法 – 跳转方法 RequestMapping(/nopermission)public String nopermission(){// 去到没有权限的 html 页面return common/nopermission;}⑤ LoginController中获取权限方法 – queryByEmployeeId
// 获取当前用户的权限列表。
ListString permissionList permissionService.queryByEmployeeId(employee.getId());⑥ service – queryByEmployeeId
// IPermissionService
ListString queryByEmployeeId(Long id);
// PermissionServiceImpl
public ListString queryByEmployeeId(Long employeeId) {return permissionMapper.queryByEmployeeId(employeeId);
}⑦ mapper – queryByEmployeeId
// PermissionMapper
ListString queryByEmployeeId(Long employeeId);
// PermissionMapper.xml
select idqueryByEmployeeId resultTypejava.lang.Stringselect expression from permission where id in (select permission_id from role_permission where role_id in(select role_id from employee_role where employee_id#{employeeId}))
/select7 Ajax请求没有权限时的拦截处理 面对Ajax请求我们应返回一组Json数据因此拦截器应有两种情况根据不同的请求返回不同的数据页面请求就返回页面Ajax请求返回一组Json数据此处页面需要走视图Ajax不走视图需要response注解 PermissionInterceptor 拦截器
Component
public class PermissionInterceptor implements HandlerInterceptor{Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 略// 判断当前拿到的 expression 在用户的权限列表中是否存在。if(!permissionList.contains(expression)){//permissionList中是否有expression// 根据请求的不同那么我们要返回时就需要碰到两种情况if(method.hasMethodAnnotation(ResponseBody.class)){// ajax 请求 需要设置响应头response.setContentType(application/json;charsetutf-8);// 向页面中写数据response.getWriter().write(new ObjectMapper().writeValueAsString(new JsonResult(false,您还没有权限操作)));} else{// 页面请求 templates文件夹相当于web中的inf文件夹// 若不存在则说明当前登录用户没有该方法的访问权限。拦截请求。并提到没有权限的页面。response.sendRedirect(/permission/nopermission);}return false;}}return true;}
}8 抽取 UserContext 工具类 登录拦截权限拦截多处使用了session因此将其抽取出来作为一个工具类使用 RequestContextHolder 工具类它是 Spring MVC 提供的工具类提供了一个静态方法可以在代码任意的地方获取 request 对象response 对象sessison 对象不需要每次自己把对象传进去存入线程中同一条线程数据共享但是这个工具类获取 session 的代码得写在好几个地方所以我们可以直接再封装为一个用于获取 session 的方法提供给其他方法调用。 ① UserContext
public class UserContext {public static final String USER_IN_SESSION user_in_session;public static final String PERMISSION_IN_SESSION permission_in_session;//使用RequestContextHolder工具类(springMVC提供存在线程中)可在代码任意位置获取//request对象response对象session对象public static HttpSession getSession(){// 此处需要的是他的子类ServletRequestAttributes attrs (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();return attrs.getRequest().getSession();}//设置当前登录用户public static void setCurrentUser(Employee employee){getSession().setAttribute(USER_IN_SESSION,employee);}//设置获取登录用户public static Employee getCurrentUser(){return (Employee) getSession().getAttribute(USER_IN_SESSION);}//设置权限集合public static void setPermission(ListString permissionList){getSession().setAttribute(PERMISSION_IN_SESSION,permissionList);}//获取权限集合public static ListString getPermission(){return (ListString) getSession().getAttribute(PERMISSION_IN_SESSION);}
}② RequestContextHolder
public static HttpSession getSession() {ServletRequestAttributes attrs (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();return attrs.getRequest().getSession();
}9 统一异常处理 对于想要提示给用户的异常信息与不想用户看到的异常信息系统级异常显示联系管理员等信息需要做两种方式的处理。 ① 自定义异常处理类
// 自定义异常处理类
public class BusinessException extends RuntimeException {// 调用父类public BusinessException(String msg){super(msg);}
}// 调用public Employee getByUsernameAndPassword(String username, String password) {if(!StringUtil.isNotEmpty(username) || !StringUtil.isNotEmpty(password)){throw new BusinessException(账号密码有误);}Employee employee employeeMapper.getByUsernameAndPassword(username,password);if(employee null){throw new BusinessException(账号密码有误);}return employee;
}② 异常捕获类 – 针对不同的异常做不同的处理
// ControllerAdvice 可直接跳转到templates目录下
// ConrolletAdvice 和 Controller 的异同点// 相同点// 有四种返回值// void: 处理方法都会定义一个 HttpServlerResponse 形参。自定义响应内容想响应什么就响应什么// String一般来说至少有一个 Model 形参响应的 HTML 格式内容// ModelAndView 一般响应 HTML 格式内容也可以响应 JSON// 自定义响应类型 响应 JSON 格式数据ResponseBody// 不同点// Controlelr 上面贴的是 RequestMapping 而我们的 ConrolletAdvice 贴的是 ExceptionHandler// ExceptionHandler异常类型 根据不同的异常类型做不同的处理。// Controller 是 在请求的过程中 访问控制器对象--业务对象--Mapper对象。在整个过程中若出现了异常。// 则统一交给我们的 ExceptionControllerAdvice 处理。需要注意一定不能try catch
ControllerAdvice
public class ExceptionControllerAdvice {// 自定义异常(想让用户看到的)ExceptionHandler(BusinessException.class)public String handlerException(BusinessException e, Model model, HandlerMethod method, HttpServletResponse response){// e 为异常model 为向前端展示的数据method为通过目标方法有无ResponseBody注解判断应返回页面还是jsonresponse 为返回响应的json// 异常也分为页面异常和 ajax 请求的异常。if(method.hasMethodAnnotation(ResponseBody.class)){// ajax 请求有ResponseBody注解response.setContentType(application/json;charsetutf-8);try {response.getWriter().write(new ObjectMapper().writeValueAsString(new JsonResult(false,e.getMessage())));} catch (IOException ex) {ex.printStackTrace();}// 走的是ajax请求不需要返回任何界面return null;} else{// 页面请求model.addAttribute(errorMsg,e.getMessage());return common/error;}}// 系统异常(不想让用户看到的)ExceptionHandler(Exception.class)public String handlerException(Exception e, Model model, HandlerMethod method, HttpServletResponse response){// 异常也分为页面异常和 ajax 请求的异常。if(method.hasMethodAnnotation(ResponseBody.class)){// ajax 请求response.setContentType(application/json;charsetutf-8);try {// 将系统异常替换成其他文本response.getWriter().write(new ObjectMapper().writeValueAsString(new JsonResult(false,系统繁忙请联系管理员)));} catch (IOException ex) {ex.printStackTrace();}return null;} else{// 页面请求model.addAttribute(errorMsg,系统繁忙请联系管理员);return common/error;}}
}③ LoginController – 不需再try
Controller
public class LoginController {Autowiredprivate IEmployeeService employeeService;Autowiredprivate IPermissionService permissionService;RequestMapping(/login)ResponseBodypublic JsonResult login(String username, String password, HttpSession session){// 登录成功Employee employee employeeService.getByUsernameAndPassword(username,password);UserContext.setCurrentUser(employee);// 获取当前用户的权限列表。ListString permissionList permissionService.queryByEmployeeId(employee.getId());UserContext.setPermission(permissionList);return new JsonResult(true,登录成功);}RequestMapping(/logout)public String logout(HttpSession session){// session.invalidate();session.removeAttribute(user_in_session);return redirect:/static/login.html;}
}