登陆MD5+盐
一、学习重点

二、学习内容
MVC设计模式
src--->druid.properties
druid.url = jdbc:mysql://127.0.0.1:3306/mvc?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
druid.username = root
druid.password = 3306
druid.driverName = com.mysql.cj.jdbc.Driver
druid.initialSize=10
druid.maxActive=20
druid.maxWait=20
mvc--->util(工具类)
util--->Dao(接口)
package com.jsoft.mvc.util;
import java.sql.SQLException;
import java.util.List;
public interface DAO<T> {
/**
* 更新
* @return
*/
int update(String sql, Object... args) throws Exception;
/**
* 通用的查询所有
*/
List<T> getForList(String sql, Object... args) throws Exception;
/**
* 通用的查询单个
*/
T get(String sql, Object... args) throws Exception;
/**
* 查询某一个列的值,统计
*/
<E> E getForValue(String sql, Object... args) throws SQLException;
}
util--->DaoImpl
package com.jsoft.mvc.util;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.List;
public class DAOImpl<T> implements DAO<T> {
private QueryRunner runner = null;
private Class<T> type;
/**
* 这个构造器中在做的事:
* 为了获取Class<T> type = Teacher.class
*/
public DAOImpl() {
runner = new QueryRunner(JDBCUtil.getDataSource());
// 获得当前类的带有泛型类型的父类(运行期this其实是DAOImpl的某个子类)
ParameterizedType ptClass = (ParameterizedType) this.getClass().getGenericSuperclass();
type = (Class<T>) ptClass.getActualTypeArguments()[0];
}
/**
* 通用的增删改
* @param sql
* @param args
* @return
* @throws Exception
*/
@Override
public int update(String sql, Object... args) throws Exception {
return runner.update(sql,args);
}
/**
* 根据sql语句查询多条记录
* @param sql
* @param args
* @return
* @throws Exception
*/
@Override
public List<T> getForList(String sql, Object... args) throws Exception {
return runner.query(sql,new BeanListHandler<>(type),args);
}
/**
* 根据sql语句查询一条记录
* @param sql
* @param args
* @return
* @throws Exception
*/
@Override
public T get(String sql, Object... args) throws Exception {
return runner.query(sql,new BeanHandler<>(type),args);
}
/**
* 根据sql语句查询某一列的值
* @param sql
* @param args
* @return
* @param <E>
* @throws SQLException
*/
@Override
public <E> E getForValue(String sql, Object... args) throws SQLException {
return (E) runner.query(sql,new ScalarHandler<>(),args);
}
}
util--->JDBCUtil
package com.jsoft.mvc.util;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.util.Properties;
public class JDBCUtil {
private static final DataSource DATA_SOURCE;
static {
Properties properties = new Properties();
try {
properties.load(JDBCUtil.class.getClassLoader().getResourceAsStream("druid.properties"));
DATA_SOURCE = DruidDataSourceFactory.createDataSource(properties);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static DataSource getDataSource() {
return DATA_SOURCE;
}
}
util--->MD5Util
package com.jsoft.mvc.util;
import org.apache.commons.codec.digest.DigestUtils;
public class MD5Util {
/**
* 获取用来加密盐
*/
public static String getSalt(){
//从我定义的一组数据中拿出几个字母或则数字或者符号当做盐
String words = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+~";
StringBuilder strb = new StringBuilder();
//从我定义的数据中取出8个字符,当做盐
for (int i = 0; i < 8; i++) {
//随机取
//生成一个0-字符串的长度的随机数[0,长度)
strb.append(words.charAt((int) Math.floor(Math.random() * words.length())));
}
return strb.toString();
}
/**
* 这个方法的参数是原始密码,在controller通过request.getParameter("")接到的写在密码框中的密码
* 返回值是经过加密的处理过后的密码
* 加盐 salt
* MD5 + 盐 加密
* MD5算法
* @param str
* @return
*/
public static String stringToMD5(String str) {
return DigestUtils.md5Hex(str.getBytes());
}
}
mvc--->filter--->EncodingFilter(字符编码集的过滤器)
package com.jsoft.mvc.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
* 字符编码集的过滤器
* 过滤拦截什么请求?
* */
@WebFilter("/*")
public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// HttpServletResponse response = (HttpServletResponse) servletResponse;
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
/**
* 给response添加响应头,text/html,后台向前台输出字符串的时候
* 当后台向前台输出的是json格式,不需要设置这个。
*/
// response.addHeader("content-type","text/html;charset=utf-8");
// 放行
filterChain.doFilter(servletRequest,servletResponse);
}
}
web
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="login.html">登录</a>
<a href="register.html">注册</a>
</body>
</html>
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Title</title>
</head>
<body>
<form action="addVip.do" method="post">
<P>
账号:<input type="text" name="username">
</P>
<p>
密码:<input type="password" name="password">
</p>
<p>
姓名:<input type="text" name="name">
</p>
<p>
性别:<input type="radio" value="男" name="gender" checked >男
<input type="radio" value="女" name="gender">女
</p>
<p>
<input type="submit" value="提交">
</p>
</form>
</body>
</html>
success.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>注册成功</h1>
<a href="login.html">请前往登录页面</a>
</body>
</html>
fail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>注册失败</h1>
<a href="register.html">请重新注册</a>
</body>
</html>
login.html
mvc--->controller
Vipcontroller
package com.jsoft.mvc.controller;
import com.jsoft.mvc.entitty.Vip;
import com.jsoft.mvc.service.VipService;
import com.jsoft.mvc.service.impl.VipServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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;
/**
* 有一个约定
* 前台提交的请求,必须提交到 /admin/xxx.do
*
* 我们当前的servlet只接受*.do结尾的请求
*
* 当我们写*.do的时候,前面不能写/
*
* 配置servlet映射的时候,*和/不能同时出现,/*除外
*/
@WebServlet("*.do")
public class Vipcontroller extends HttpServlet {
//controller调用service
private VipService vipService= new VipServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// /admin/addVip.do
String servletPath = req.getServletPath();
System.out.println(servletPath);
//我现在可以拿到一个servlet的请求路径,在我这个类中,有一个addVip方法
//1、去掉第一个/ admin/addVip.do
String methodName = servletPath.substring(1);
//2、截取成addVip方法
methodName = methodName.substring(methodName.lastIndexOf("/")+ 1,methodName.length() -3);
//3、利用反射执行addVip方法
try {
//a.拿到当前类的要执行的方法对象
Method method = getClass().getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);
//b.让方法执行
method.invoke(this,req,resp);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
protected void addVip(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
String gender = req.getParameter("gender");
String name = req.getParameter("name");
Vip vip = new Vip(username,password,gender,name);
int i = vipService.register(vip);
if (i>0){
resp.sendRedirect(req.getContextPath() + "/success.html");
}else {
resp.sendRedirect(req.getContextPath() + "/fail.html");
}
}
protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("login ...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
mvp--->entity
vip
package com.jsoft.mvc.entity;
/**
* 和表对应的实体类,entity
* 要求:
* 1、类名和表名相同
* 2、类中的属性和表中的字段名相同
* 3、类中只能由对应的set、get方法和需要用到的构造器,如果有需要,可以写toString
* 4、序列化,实现序列化接口
* */
public class Vip {
private static final long serialVersionUID = -6849794470754667710L;
private Integer id;
private String username;
private String password;
private String gender;
private String name;
private String profile;
private String salt;
public Vip() {
}
public Vip(String username, String password, String gender, String name) {
this.username = username;
this.password = password;
this.gender = gender;
this.name = name;
}
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getProfile() {
return profile;
}
public void setProfile(String profile) {
this.profile = profile;
}
}
mvc--->service
Vipservice
package com.jsoft.mvc.service;
import com.jsoft.mvc.entity.Vip;
//业务层
//业务:软件的功能
//登录,注册
//在dao层写了一个方法save,保存
public interface VipService {
int register(Vip vip);
}
Impl--->VipServiceImpl(实现类)
package com.jsoft.mvc.service.impl;
import com.jsoft.mvc.dao.VipDao;
import com.jsoft.mvc.dao.impl.VipDaoImpl;
import com.jsoft.mvc.entity.Vip;
import com.jsoft.mvc.service.VipService;
import com.jsoft.mvc.util.MD5Util;
//在service层调用dao层
/**
* 密码在加盐加密过后登陆的时候怎么办???
* 登陆的时候,肯定输入的还是123456
* 登陆的时候还得按照加盐加密的形式来比对,还需要拿着123456和之前加密时候的盐再按照规则加密过后再比对
*
* 问题:我们能找到上次加密的时候用到的那个盐吗???
* 盐 怎么处理???
* 我们需要把加密时候用的盐记录下来,登陆的时候还需要使用!!!
*
* 唯一的办法,就是把盐也存在数据库里
*/
public class VipServiceImpl implements VipService {
private VipDao dao = new VipDaoImpl();
@Override
public int register(Vip vip) {
//注册的业务执行的就是保存的操作
try {
//密码的加密处理
//生成盐
String salt = MD5Util.getSalt();
//对密码进行加密
// String newPassword = MD5Util.stringToMD5(vip.getPassword() + salt)
//加密过后还要重新赋值给vip
vip.setPassword(MD5Util.stringToMD5(vip.getPassword() + salt));
vip.setSalt(salt);
return dao.save(vip);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
mvc--->dao
VipDao(接口)
package com.jsoft.mvc.dao;
import com.jsoft.mvc.entity.Vip;
public interface VipDao {
int save(Vip vip) throws Exception;
}
impl--->VipDaoImpl(实现类)
package com.jsoft.mvc.dao.impl;
import com.jsoft.mvc.dao.VipDao;
import com.jsoft.mvc.entity.Vip;
import com.jsoft.mvc.util.DAOImpl;
public class VipDaoImpl extends DAOImpl<Vip> implements VipDao {
@Override
public int save(Vip vip) throws Exception {
String sql = "insert into vip(username,password,gender,name,salt) values(?,?,?,?,?)";
return update(sql,vip.getUsername(),vip.getPassword(),vip.getGender(),vip.getName(),vip.getSalt());
}
}
三、笔记内容
MVC架构:
是一种软件架构模式,把整个软件分为三层:Model、View、Controller
Model:模型----获取数据,并且处理数据,返回给Controller。
- entity:数据库实体类 User----user表
- service:业务控制层,其余的活都交给service
- dao:数据模型层----操作数据库,执行sql
View:视图----看见的页面,渲染数据,渲染页面。
Controller:控制器----servlet,接请求,给响应。
耦合度:代码之间的关联关系。
为什么要分层?MVC,降耦合。重合性高。可维护性高。
调用关系:
View层发起请求---Controller---Service---Dao---Service---Controller---View
导入jar包,导入js文件,复制粘贴之前的JDBC工具类,昨天的字符集的过滤器
问?
我们之前的做法,一个servlet就只能处理一个请求?
一个servlet能不能处理多个post请求?
**可以的(利用反射)**

浙公网安备 33010602011771号