2022-9-03 第七小组 学习日记 (day58)MVC

目录

MVC

目的:

调用关系:

MVC优缺点

优点

缺点

实例

controller:

VipController类:

dao:

VipDao接口:定义一个save方法:

VipDaoImpl类:操作数据库

entiy:

Vip实体类:

filter:

EncodingFilter:过滤器,我这个过滤器就是防止在传输过程中的时候产生乱码:

service:

VipService:注册的方法

VipServiceImpl:(脏活累活给我干)

util:工具类

DAO:

DAOImpl:

JDBCUtil

MD5Util:

总结


MVC

MVC是一种软件架构模式,把整个软件分为三层:Model,View,Controller

Model:模型---负责获取并数据,并且处理数据,返回给controller

        entity:数据库的实体类

        service:业务控制层,其余的话都交给service

        dao:databaseObject数据模型层:只操作数据库

View:视图---看见的页面,渲染数据,渲染页面,负责展示而且允许用户编辑来自应用程序的Model对象,View对象用来构建用户界面,与用户交互。

Controller:控制器---servlet,接请求,给出响应,负责传递数据,监听各种事件,管理其他对象生命周期

目的:

耦合度(代码之间的关联关系)分层,把程序分层,改bug的时候,不用找的眼花缭乱,方便找

降低耦合,重用性,可维护性比较高

调用关系:

View层发起请求---Controller---Servlet---Dao---Servlet---Controller---View

MVC优缺点

优点

  • 多视图共享一个模型,大大提高了代码的可重用性
  • MVC 三个模块相互独立,松耦合架构,降低耦合度
  • 控制器提高了应用程序的灵活性和可配置性
  • 有利于软件工程化管理

总之,我们通过 MVC 设计模式最终可以打造出一个松耦合+高可重用性+高可适用性的完美架构。

缺点

  • 原理复杂
  • 增加了系统结构和实现的复杂性
  • 视图对模型数据的低效率访问

MVC 并不适合小型甚至中型规模的项目,花费大量时间将 MVC 应用到规模并不是很大的应用程序,通常得不偿失,所以对于 MVC 设计模式的使用要根据具体的应用场景来决定。

实例

接下来通过一个简单的项目结构,来展示一下: 

 controller包代表的是控制器,用来接请求,给响应

dao包代表数据模型层,只用来操作数据库

entiy包代表实体类,用来储存元素并提供get/set/构造器方法

filter包代表的是过滤器,用来筛选信息的

service包代表的是业务控制层,其余的“脏活累活都交给他干”

util包代表工具类

因为是结合实例写的,所以会有关于每个类中的一些做项目时产生的问题,就直接解决了

controller:

我们之前的做法是一个servlet就只处理一个请求

那么一个servlet能不能处理过个post请求?可以,利用反射:

VipController类:

@WebServlet("*.do")
public class VipController extends HttpServlet {
    //调用service
    private VipService vipService = new VipServiceImpl();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取请求的路径
        String servletPath = req.getServletPath();
        System.out.println(servletPath);
        //截取地址:截取成eg:vip
        String method =servletPath.substring(1);
        method = method.substring(method.lastIndexOf("/")+1,method.length()-3);
        //利用反射执行vip方法
//        拿到当前类对象
        try {
            Method method1 = getClass().getDeclaredMethod(method, HttpServletRequest.class, HttpServletResponse.class);
            method1.invoke(this,req,resp);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
    private void vip(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");
        System.out.println(username+password+gender+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");
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

dao:

VipDao接口:定义一个save方法:

public interface VipDao {
    int save(Vip vip) throws Exception;
}

VipDaoImpl类:操作数据库

public class VipDaoImpl extends DAOImpl<Vip> implements VipDao {
    @Override
    public int save(Vip vip) throws Exception {
        String sql ="insert into mvc(username,password,gender,name,salt) values (?,?,?,?,?)";
        System.out.println("sql");
        return update(sql,vip.getUsername(),vip.getPassword(),vip.getGender(),vip.getName(),vip.getSalt());
    }
}

entiy:

Vip实体类:

先整个序列化,然后创建对应数据库里所有的属性。并赋予get/set方法

package mvc.entiy;
 
import java.io.Serializable;
 
public class Vip implements Serializable {
    private static final long serialVersionUID=-12389731289739127L;
    private Integer id;
    private String username;
    private String password;
    private String gender;
    private String profile;
    private String name;
    private String salt;
 
    public String getSalt() {
        return salt;
    }
 
    public void setSalt(String salt) {
        this.salt = 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 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 getProfile() {
        return profile;
    }
 
    public void setProfile(String profile) {
        this.profile = profile;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    @Override
    public String toString() {
        return "Vip{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", gender='" + gender + '\'' +
                ", profile='" + profile + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

filter:

EncodingFilter:过滤器,我这个过滤器就是防止在传输过程中的时候产生乱码:

@WebFilter("/*")
public class EncodingFilter implements Filter {
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
 
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        System.out.println("filter");
        servletRequest.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
 
//        放行
        filterChain.doFilter(servletRequest,servletResponse);
    }
}

service:

VipService:注册的方法

public interface VipService {
    //注册的方法
    int register(Vip vip);
}

VipServiceImpl:(脏活累活给我干)

这里面有个不算拓展的拓展:进行密码的加密处理,毕竟密码不可能直接就存到数据库里,万一数据库被黑客或者某些人攻击或者窃取,这些密码不久流失了吗

进行密码加密:

——调用在工具类里写的getSalt方法,获取盐,加到密码上

——利用MD5加密处理:MD5Util.stringToMD5(密码);

——再把密码存到Vip的set方法里

密码在加盐加密过后登录的时候怎么办?

——登录的时候,还得按照加盐加密的形式来对比,还得需要拿着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.setPassword(newPassword);
//            vip.setPassword(MD5Util.stringToMD5(vip.getPassword() + MD5Util.getSalt()));
            System.out.println("service");
            vip.setSalt(salt);
            return dao.save(vip);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

util:工具类

DAO:

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;
 
}

DAOImpl:

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 {
        System.out.println("成功");
        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);
    }
}

JDBCUtil

用德鲁伊来连接数据库

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;
    }
 
}

MD5Util:

加密方法

public class MD5Util {
    /*
        这个方法的参数是原始密码,在controller通过request.getParameter("")接到的写在密码框中的密码
        返回值是经过加密处理过后的密码
        加盐 salt
        MD5+盐 加密
     */
    public static String getSalt(){
//        从我定义的一组数据中拿出几个字母或者数字或者符号当作盐
        String words="qwertyuioplkjhgfdsazxcvbnm,./;'[]~!@#$%^&*()_+-=0123456789";
        StringBuilder strb = new StringBuilder();
        for (int i = 0; i <8 ; i++) {
            //从我定义的数据中取x个字符当做盐,这里取了八个
//            随机取,生成一个0到字符串的长度的随机数
            strb.append(words.charAt((int)Math.floor(Math.random()*words.length()-1)));
        }
        return strb.toString();
    }
    public static String stringToMD5(String str){
        return DigestUtils.md5Hex(str.getBytes());
    }
}

总结

        今天使用MVC架构练习登录、注册系统,这样写的代码耦合度较低,使用较方便,通过这次练习能初步认识项目内容,MVC架构的代码量极大(对我来说),各类间的联系很强,互相调用调来调去调得我快晕😵了,行百里路半九十接下来六十天将进入实战阶段,我能在实战得到锻炼得到提升,加油坚持就是胜利!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值