• 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类:

    1. @WebServlet("*.do")
    2. public class VipController extends HttpServlet {
    3. //调用service
    4. private VipService vipService = new VipServiceImpl();
    5. @Override
    6. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    7. //获取请求的路径
    8. String servletPath = req.getServletPath();
    9. System.out.println(servletPath);
    10. //截取地址:截取成eg:vip
    11. String method =servletPath.substring(1);
    12. method = method.substring(method.lastIndexOf("/")+1,method.length()-3);
    13. //利用反射执行vip方法
    14. // 拿到当前类对象
    15. try {
    16. Method method1 = getClass().getDeclaredMethod(method, HttpServletRequest.class, HttpServletResponse.class);
    17. method1.invoke(this,req,resp);
    18. } catch (NoSuchMethodException e) {
    19. throw new RuntimeException(e);
    20. } catch (InvocationTargetException e) {
    21. throw new RuntimeException(e);
    22. } catch (IllegalAccessException e) {
    23. throw new RuntimeException(e);
    24. }
    25. }
    26. private void vip(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    27. String username = req.getParameter("username");
    28. String password = req.getParameter("password");
    29. String gender = req.getParameter("gender");
    30. String name = req.getParameter("name");
    31. System.out.println(username+password+gender+name);
    32. Vip vip = new Vip(username,password,gender,name);
    33. int i = vipService.register(vip);
    34. if(i>0){
    35. resp.sendRedirect(req.getContextPath()+"/success.html");
    36. }else{
    37. resp.sendRedirect(req.getContextPath()+"/fail.html");
    38. }
    39. }
    40. @Override
    41. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    42. doGet(req, resp);
    43. }
    44. }

    dao:

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

    1. public interface VipDao {
    2. int save(Vip vip) throws Exception;
    3. }

    VipDaoImpl类:操作数据库

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

    entiy:

    Vip实体类:

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

    1. package mvc.entiy;
    2. import java.io.Serializable;
    3. public class Vip implements Serializable {
    4. private static final long serialVersionUID=-12389731289739127L;
    5. private Integer id;
    6. private String username;
    7. private String password;
    8. private String gender;
    9. private String profile;
    10. private String name;
    11. private String salt;
    12. public String getSalt() {
    13. return salt;
    14. }
    15. public void setSalt(String salt) {
    16. this.salt = salt;
    17. }
    18. public Vip(){
    19. }
    20. public Vip(String username, String password, String gender, String name) {
    21. this.username = username;
    22. this.password = password;
    23. this.gender = gender;
    24. this.name = name;
    25. }
    26. public Integer getId() {
    27. return id;
    28. }
    29. public void setId(Integer id) {
    30. this.id = id;
    31. }
    32. public String getUsername() {
    33. return username;
    34. }
    35. public void setUsername(String username) {
    36. this.username = username;
    37. }
    38. public String getPassword() {
    39. return password;
    40. }
    41. public void setPassword(String password) {
    42. this.password = password;
    43. }
    44. public String getGender() {
    45. return gender;
    46. }
    47. public void setGender(String gender) {
    48. this.gender = gender;
    49. }
    50. public String getProfile() {
    51. return profile;
    52. }
    53. public void setProfile(String profile) {
    54. this.profile = profile;
    55. }
    56. public String getName() {
    57. return name;
    58. }
    59. public void setName(String name) {
    60. this.name = name;
    61. }
    62. @Override
    63. public String toString() {
    64. return "Vip{" +
    65. "id=" + id +
    66. ", username='" + username + '\'' +
    67. ", password='" + password + '\'' +
    68. ", gender='" + gender + '\'' +
    69. ", profile='" + profile + '\'' +
    70. ", name='" + name + '\'' +
    71. '}';
    72. }
    73. }

    filter:

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

    1. @WebFilter("/*")
    2. public class EncodingFilter implements Filter {
    3. @Override
    4. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    5. HttpServletResponse response = (HttpServletResponse) servletResponse;
    6. System.out.println("filter");
    7. servletRequest.setCharacterEncoding("utf-8");
    8. response.setCharacterEncoding("utf-8");
    9. // 放行
    10. filterChain.doFilter(servletRequest,servletResponse);
    11. }
    12. }

    service:

    VipService:注册的方法

    1. public interface VipService {
    2. //注册的方法
    3. int register(Vip vip);
    4. }

    VipServiceImpl:(脏活累活给我干)

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

    进行密码加密:

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

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

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

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

    登录的时候,还得按照加盐加密的形式来对比,还得需要拿着123456密码和之前加密的时候的盐再按照规则加密过后再比对

    问题:我们能找到上次加密的时候用的那个盐吗? 我们需要把加密时候用的盐记录下来,登录的时候还需要使用!!!

    唯一的办法,就是把盐存在数据库里

    1. public class VipServiceImpl implements VipService {
    2. private VipDao dao = new VipDaoImpl();
    3. @Override
    4. public int register(Vip vip) {
    5. //注册的业务执行的就是保存的操作
    6. try {
    7. //密码的加密处理
    8. //生成盐
    9. String salt = MD5Util.getSalt();
    10. String newPassword = MD5Util.stringToMD5(vip.getPassword() + salt);
    11. vip.setPassword(newPassword);
    12. // vip.setPassword(MD5Util.stringToMD5(vip.getPassword() + MD5Util.getSalt()));
    13. System.out.println("service");
    14. vip.setSalt(salt);
    15. return dao.save(vip);
    16. } catch (Exception e) {
    17. throw new RuntimeException(e);
    18. }
    19. }
    20. }

    util:工具类

    DAO:

    1. public interface DAO<T> {
    2. /**
    3. * 更新
    4. * @return
    5. */
    6. int update(String sql,Object ... args) throws Exception;
    7. /**
    8. * 通用的查询所有
    9. */
    10. List<T> getForList(String sql,Object... args) throws Exception;
    11. /**
    12. * 通用的查询单个
    13. */
    14. T get(String sql,Object...args) throws Exception;
    15. /**
    16. * 查询某一个列的值,统计
    17. */
    18. <E> E getForValue(String sql,Object ... args) throws SQLException;
    19. }

    DAOImpl:

    1. public class DAOImpl<T> implements DAO<T> {
    2. private QueryRunner runner = null;
    3. private Class<T> type;
    4. /**
    5. * 这个构造器中在做的事:
    6. * 为了获取Class type = Teacher.class
    7. */
    8. public DAOImpl() {
    9. runner = new QueryRunner(JDBCUtil.getDataSource());
    10. // 获得当前类的带有泛型类型的父类(运行期this其实是DAOImpl的某个子类)
    11. ParameterizedType ptClass = (ParameterizedType) this.getClass().getGenericSuperclass();
    12. type = (Class<T>) ptClass.getActualTypeArguments()[0];
    13. }
    14. /**
    15. * 通用的增删改
    16. * @param sql
    17. * @param args
    18. * @return
    19. * @throws Exception
    20. */
    21. @Override
    22. public int update(String sql, Object... args) throws Exception {
    23. System.out.println("成功");
    24. return runner.update(sql,args);
    25. }
    26. /**
    27. * 根据sql语句查询多条记录
    28. * @param sql
    29. * @param args
    30. * @return
    31. * @throws Exception
    32. */
    33. @Override
    34. public List<T> getForList(String sql, Object... args) throws Exception {
    35. return runner.query(sql,new BeanListHandler<>(type),args);
    36. }
    37. /**
    38. * 根据sql语句查询一条记录
    39. * @param sql
    40. * @param args
    41. * @return
    42. * @throws Exception
    43. */
    44. @Override
    45. public T get(String sql, Object... args) throws Exception {
    46. return runner.query(sql,new BeanHandler<>(type),args);
    47. }
    48. /**
    49. * 根据sql语句查询某一列的值
    50. * @param sql
    51. * @param args
    52. * @return
    53. * @param
    54. * @throws SQLException
    55. */
    56. @Override
    57. public <E> E getForValue(String sql, Object... args) throws SQLException {
    58. return (E) runner.query(sql,new ScalarHandler<>(),args);
    59. }
    60. }

    JDBCUtil

    用德鲁伊来连接数据库

    1. public class JDBCUtil {
    2. private static final DataSource DATA_SOURCE;
    3. static {
    4. Properties properties = new Properties();
    5. try {
    6. properties.load(JDBCUtil.class.getClassLoader().getResourceAsStream("druid.properties"));
    7. DATA_SOURCE = DruidDataSourceFactory.createDataSource(properties);
    8. } catch (IOException e) {
    9. throw new RuntimeException(e);
    10. } catch (Exception e) {
    11. throw new RuntimeException(e);
    12. }
    13. }
    14. public static DataSource getDataSource() {
    15. return DATA_SOURCE;
    16. }
    17. }

    MD5Util:

    加密方法

    1. public class MD5Util {
    2. /*
    3. 这个方法的参数是原始密码,在controller通过request.getParameter("")接到的写在密码框中的密码
    4. 返回值是经过加密处理过后的密码
    5. 加盐 salt
    6. MD5+盐 加密
    7. */
    8. public static String getSalt(){
    9. // 从我定义的一组数据中拿出几个字母或者数字或者符号当作盐
    10. String words="qwertyuioplkjhgfdsazxcvbnm,./;'[]~!@#$%^&*()_+-=0123456789";
    11. StringBuilder strb = new StringBuilder();
    12. for (int i = 0; i <8 ; i++) {
    13. //从我定义的数据中取x个字符当做盐,这里取了八个
    14. // 随机取,生成一个0到字符串的长度的随机数
    15. strb.append(words.charAt((int)Math.floor(Math.random()*words.length()-1)));
    16. }
    17. return strb.toString();
    18. }
    19. public static String stringToMD5(String str){
    20. return DigestUtils.md5Hex(str.getBytes());
    21. }
    22. }
  • 相关阅读:
    腾讯云16核服务器配置有哪些?CPU型号处理器主频性能
    Qt实现动态桌面小精灵(含源码)
    死锁(什么是死锁、怎样预防死锁、避免死锁、检测和解除)
    C/C++ 面试八股文
    从0开始python学习-26.selenium 强制等待、显示等待、隐式等待
    [C++][算法基础]欧拉函数(线性筛)
    SAP 接口主动推送企业微信异常消息
    技术分享 | 误删表以及表中数据,该如何恢复?
    cmake下的abiFilters和ndk下的abiFilters的区别
    CTreeCtrl自绘
  • 原文地址:https://blog.csdn.net/weixin_49627122/article/details/126678697