小言_互联网的博客

众筹项目开发

269人阅读  评论(0)

项目计划

  • 完成登录功能 同步请求方式 密码加密 注销功能

第一章 登录功能开发

1.1 页面导入步骤

1.1.1 拷贝静态资源,放main工程webapp/static目录下

1.1.2 创建登录页面

1.1.3 相对路径,绝对路径问题

  • 绝对路径

不可改变的路径称之为绝对路径
本地路径:以盘符开始的路径称之为绝对路径, c:/test/test.html
网络路径:以协议,域名,端口号所组合的路径为绝对路径
http://localhost:8080/atcrowdfunding/image/xxx.jpg
http:// www.xxx.com/test/test.com

  • 相对路径:

可以改变的路径
默认的相对路径需要一个参考的位置,取值为当前资源的访问路径

  • 路径以斜杠开头

路径以斜杠开头,也是相对路径,但是参考的位置和默认的相对路径不一样

  • 前台路径(img, css, js, form)

参考的位置是服务器的根路径
response.sendRedirect(request.getContextPath()+"/xxx.jsp");

  • 后台路径( java, xml )

参考的位置是web应用的根路径

request.getRequestDispatcher("/xxx.jsp").forward(req,resp);

1.2 项目启动监听器

1.2.1 WEB监听器

  1. 监听当前应用ServletContext对象
    javax.servlet.ServletContextListener
    监听ServletContext对象创建和销毁.
    应用场景:
    在服务器启动时建立数据库表结构,初始化数据库.
    在服务器启动时,将数据库常量数据加载到内存,提供访问效率.
    在服务器启动时,获取项目上下文路径,存放到application域,给页面使用.
    存放计数器,计算在线用户数.
    javax.servlet.ServletContextAttributeListener
    监听ServletContext对象的属性的变化:添加,覆盖,删除
  2. 监听器HttpSession对象
    javax.servlet.http.HttpSessionListener
    监听HttpSession对象的创建和销毁
    javax.servlet.http.HttpSessionAttributeListener
    监听HttpSession对象的属性变化:添加,覆盖,删除
  3. 监听HttpServletRequest对象
    javax.servlet.ServletRequestListener
    监听HttpServletRequest对象的创建和销毁
    javax.servlet.ServletRequestAttributeListener
    监听HttpServletRequest对象的属性变化:添加,覆盖,删除

1.2.2 自定义监听器

  1. 在服务器启动时,将应用上下文路径存放到application域中
  2. 在JSP页面中使用EL表示式获取应用上下文路径使用它.
  3. 编写监听器
package com.atguigu.atcrowdfunding.listener;
 
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener; 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 
import com.atguigu.atcrowdfunding.constant.AppConst;
 
/**
 * 应用启动监听器
 * 应用启动的时候保存一些共享的数据信息
 */
public class AppStartUpListener implements ServletContextListener {
  Logger logger = LoggerFactory.getLogger(getClass());  
  /**
   * 项目启动调用
   */
  @Override
  public void contextInitialized(ServletContextEvent sce) {
    ServletContext servletContext = sce.getServletContext();        
    String contextPath = servletContext.getContextPath();//   /atcrowdfunding-main
    //保存项目路径
    servletContext.setAttribute(AppConst.APP_PATH, contextPath);
    logger.info("项目启动完成....");
  }
  /**
   * 项目停止调用
   */
  @Override
  public void contextDestroyed(ServletContextEvent sce) {
  }  
} 

1.2.3 注册到web.xml中

<!--项目启动监听器  -->
<listener>
    <listener-class>com.atguigu.atcrowdfunding.listener.AppStartUpListener</listener-class>
</listener>

1.3 前端流程业务

设计 首页

设计 登录页面

设计 管理员登录后主页面

设计 会员登录后主页面

1.3.5 登录涉及表

  • t_admin 管理员
  • t_member 会员表

1.3.6 流程图

用户登录时序图

1.4 抽取公共菜单

1.4.1 完成登录控制流转

/**
 * 处理登录请求
 */
@Controller
public class LoginController {
	Logger logger = LoggerFactory.getLogger(getClass()); 
	@RequestMapping("/login")
public String login(TAdmin admin,HttpSession session,Model model){
	//1、进行登录
	logger.debug("用户进行登录:用户名:{}  密码:	{}",admin.getLoginacct(),admin.getUserpswd());
	return "main";
}
}

1.4.2 抽取页面side-bar.jsp

/WEB-INF/jsp/common/side-bar.jsp

1.4.3 包含菜单页面

<%@include file="/WEB-INF/jsp/common/menu.jsp" %>

1.4.4 静态包含和动态包含区别

  • 静态包含

    将两个页面合并一个页面,编译生成一个类;
    <%@ include file="/WEB-INF/jsp/common/menu.jsp "%>

  • 动态包含

    生成多个类
    <jsp:include page="/WEB-INF/jsp/common/menu.jsp "></jsp:include>

1.5 表单重复提交-重定向

完成登录控制流转

/**
 * 处理登录请求
 */
@Controller
public class LoginController {
	Logger logger = LoggerFactory.getLogger(getClass());
 
@RequestMapping("/main ")
public String main(HttpSession session){
	return "main";
}
 
@RequestMapping("/login")
public String login(TAdmin admin,HttpSession session,Model model){
	//1、进行登录
	logger.debug("用户进行登录:用户名:{}  密码:{}",admin.getLoginacct(),admin.getUserpswd()); 
	//2、登录完成跳转到main页面。重定向到main?
	//转发能访问受保护的资源,重定向不能;
	return "redirect:/main ";
}
}

1.6 基本逻辑开发

  1. 增加index.jsp
  2. 增加index.jsp到login.jsp页面的跳转
  3. 修改登录页面login.jsp的表单及验证表单数据,提交请求
  4. 处理登录请求
  5. 处理器类(TAdminController),处理请求方式,根据登录进行判断并跳转页面
  6. 业务层接口(TAdminService)和实现类(TAdminServiceImpl)
  7. DAO接口(TAdminMapper )和映射(TAdminMapper.xml)
  8. 创建TAdmin/TMember实体类
  9. main.jsp页面

1.7 加密与解密

1.7.1 密文

1.7.2 加密算法分类

1.7.2.1 对称加密

常见加密算法
DES : Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。
AES : Advanced Encryption Standard, 高级加密标准 .在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。
特点:
加密速度快, 可以加密大文件
密文可逆, 一旦密钥文件泄漏, 就会导致数据暴露
加密后编码表找不到对应字符, 出现乱码
一般结合Base64使用

1.7.2.2 非对称加密

RSA

1.7.2.3 不可逆加密

MD5算法具有以下特点:
1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。(32位长度字符串)
2、容易计算:从原数据计算出MD5值很容易。(不可逆算法)
3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
4、强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的
MD5加密后的内容可以通过暴力破解(网站当中使用验证码,目的就是为了防止暴力破解)

消息摘要
消息摘要(Message Digest)又称为数字摘要(Digital Digest)
它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生
特点
无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。例如应用MD5算法摘要的消息有128个比特位,用SHA-1算法摘要的消息最终有160比特位的输出
只要输入的消息不同,对其进行摘要以后产生的摘要消息也必不相同;但相同的输入必会产生相同的输出
消息摘要是单向、不可逆的
常见算法 :
MD5
SHA1
SHA256
SHA512
彩虹表:穷举;

1.7.3 常用加解密算法

Base64位加密(可加密解密)
MD5加密(加密不可逆)
SHA 1加密(加密不可逆)
AES加密(需要密钥才能解密)
RSA加密(公钥加密,私钥解密)

1.8 登录完成

1.8.1 登录成功

展示session用户信息

1.8.2 登录失败

1.8.2.1 展示错误消息

@RequestMapping("/login")
public String login(TAdmin admin,HttpSession session,Model model){
	//1、进行登录
	logger.debug("用户进行登录:用户名:{}  密码:	{}",admin.getLoginacct(),admin.getUserpswd());
 
	//2、调用业务进行登录,成功返回对象,失败返回null
	TAdmin loginUser = adminUserService.login(admin);
 
	if(loginUser == null){
	logger.error("登录失败:用户名:{}",admin.getLoginacct());
	//失败了去登录页面重新登录;带了forward:、redirect:前缀的视图解析器不拼串
	model.addAttribute(AppConst.MSG, "账号或密码错误");
	//参数类型是一个对象;
	//1)、自动将页面传来的值和对象里面的属性一一绑定
	//2)、这个对象默认也会放在请求域中;取值用的key?
	//    1)、对象类名首字母小写; Admin   admin
	//        2)、不符合驼峰命名的,就是类名;TAdmin
	return "forward:/WEB-INF/views/login.jsp";
}
	session.setAttribute(AppConst.LOGIN_USER, loginUser);
	//2、登录完成跳转到main页面。重定向到main
	return "redirect:/main ";
}

1.8.2.2 表单数据回显,并提示错误消息

<div class="alert alert-danger">
${msg }
</div>
<div class="form-group has-success has-feedback">
<input type="text" class="form-control" name="loginacct"
placeholder="请输入登录账号" autofocus value="${TAdmin.loginacct }"> 
<span class="glyphicon glyphicon-user form-control-feedback"></span>
</div>

1.9 菜单查询并组装完成

1.9.1 TMenu

package com.atguigu.atcrowdfunding.bean;
 
import java.util.ArrayList;
import java.util.List;
 
public class TMenu {
    private Integer id; 
    private Integer pid; 
    private String name; 
    private String url; 
    private String icon;    
    //保存当前菜单的所有子菜单的
    private List<TMenu> childMenus = new ArrayList<>();    
}

1.9.2 SystemMenuService/SystemMenuServiceImpl

package com.atguigu.atcrowdfunding.service;
 
import java.util.List; 
import com.atguigu.atcrowdfunding.bean.TMenu;
 
/**系统菜单服务*/
public interface SystemMenuService {
List<TMenu> listMenus(); 
}
package com.atguigu.atcrowdfunding.service.impl;
 
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import com.atguigu.atcrowdfunding.bean.TMenu;
import com.atguigu.atcrowdfunding.mapper.TMenuMapper;
import com.atguigu.atcrowdfunding.service.SystemMenuService;
 
@Service
public class SystemMenuServiceImpl implements SystemMenuService { 
@Autowired
TMenuMapper menuMapper;
 
@Override
public List<TMenu> listMenus() {
// 1、查出所有菜单;
List<TMenu> list = menuMapper.selectByExample(null); 
//父菜单保存数组
List<TMenu> parentMenus = new ArrayList<>();
//父菜单按照id缓存起来了
Map<Integer, TMenu> cache = new HashMap<>(); 
// 2、组装成页面能用的有父子关系的菜单结构
// 2.1)、挑出所有的菜单中哪些是父菜单
for (TMenu parentMenu : list) {
if (parentMenu.getPid() == 0) {
//说明这是一个父菜单
parentMenus.add(parentMenu);
//缓存起来方便以后按照id查询
cache.put(parentMenu.getId(), parentMenu);
} 
}
// 2.2)、找到所有父菜单的所有子菜单   8*8=64
for (TMenu tMenu : list) {
//遍历所有子菜单
if(tMenu.getPid()!=0){
//子菜单找到他的父菜单  
Integer pid = tMenu.getPid();
//在缓存中找到之前保存的父菜单。按照当前菜单的pid等于缓存中父菜单的id;
TMenu parent = cache.get(pid);
parent.getChildMenus().add(tMenu);
}
}
return parentMenus;
}
}

1.9.3 显示菜单

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<ul style="padding-left:0px;" class="list-group">
	<c:forEach items="${loginMenuList }" var="parentMenu">
		<c:if test="${empty parentMenu.children}">
			<li class="list-group-item tree-closed" >
				<a href="${PATH}/${parentMenu.url}"><i class="${parentMenu.icon}"></i>
 ${parentMenu.name }</a> 
			</li>
		</c:if>
		<c:if test="${not empty parentMenu.children}">
			<li class="list-group-item tree-closed">
				<span><i class="${parentMenu.icon }"></i> ${parentMenu.name} 
<span class="badge" style="float:right">${parentMenu.children.size() }</span></span> 
				<ul style="margin-top:10px;display:none;">
					<c:forEach items="${parentMenu.children }" var="menu">
						<li style="height:30px;">
							<a href="${PATH}/${menu.url}">
<i class="${menu.icon }"></i> ${menu.name }</a> 
						</li>
					</c:forEach>					
				</ul>
			</li>
		</c:if>		
	</c:forEach>	
</ul>

转载:https://blog.csdn.net/weixin_43902449/article/details/104723566
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场