登陆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号