smbms超市管理系统(项目流程笔记,遇见问题的总结)

一、项目搭建准备工作

【注意】jdbc配置url:useSSL=false

  1. 搭建一个Maven Web项目

  2. 配置Tomcat

    web项目的默认上下文:/smbms

  3. 测试项目是否能跑起来

  4. 导入项目中会遇到的包

    jsp, Servlet, mysql驱动, jstl, standard

  5. 编写实体类pojo(表和类映射)

    User、 Bill、 Role、 Provider

  6. 编写基础公共类

    1. 数据库配置文件

      driver=com.mysql.jdbc.Driver
      url=jdbc:mysql://127.0.0.1:3306/smbms?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
      user=root
      password=dxw1997423
      
    2. 通过类加载器读取上述配置文件的资源

      InputStream is = baseDao.class.getClassLoader().getResourceAsStream("db.properties");
      

      Class是当前类的Class对象,Class.getClassLoader()是获取当前类的类加载器。类加载器的大概作用是当需要使用一个类时,加载该类的".class"文件,并创建对应的class对象,将class文件加载到虚拟机的内存。getResourceAsStream()是获取资源的输入流。类加载器默认是从classPath路径加载资源。
      参考链接

    3. 编写数据库的公共类

      package com.duan.dao;
      
      import java.io.IOException;
      import java.io.InputStream;
      import java.sql.*;
      import java.util.Properties;
      
      //操作数据库的公共类
      public class baseDao {
          private static String driver;
          private static String url;
          private static String username;
          private static String password;
      
          static {
              Properties properties = new Properties();
              //通过类加载器读取对应的资源
              InputStream is = baseDao.class.getClassLoader().getResourceAsStream("db.properties");
      
              try{
                  properties.load(is);
              }catch (IOException e){
                  e.printStackTrace();
              }
      
              driver = properties.getProperty("driver");
              url = properties.getProperty("url");
              username = properties.getProperty("user");
              password = properties.getProperty("password");
          }
      
          //获取数据库链接
          public static Connection getConnection(){
              Connection connection = null;
              try{
                  Class.forName(driver); //得到数据库的连接对象。properties中的:driver=com.mysql.jdbc.Driver
                  connection = DriverManager.getConnection(url, username, password);
              }catch (Exception e){
                  e.printStackTrace();
              }
      
              return connection;
          }
      
          //编写查询公共类
          public static ResultSet execute(Connection connection, String sql, Object []params, ResultSet resultSet, PreparedStatement preparedStatement) throws SQLException {
              preparedStatement = connection.prepareStatement(sql);
      
              for(int i = 0; i < params.length; i++){
                  //setObject,占位符从1开始,但是我们的数组是从0开始
                  preparedStatement.setObject(i+1, params[i]);
              }
      
              resultSet = preparedStatement.executeQuery();
              return resultSet;
          }
      
          //编写增删改查公共方法
          public static int execute(Connection connection, String sql, Object []params, PreparedStatement preparedStatement) throws SQLException {
              preparedStatement = connection.prepareStatement(sql);
      
              for(int i = 0; i < params.length; i++){
                  //setObject,占位符从1开始,但是我们的数组是从0开始
                  preparedStatement.setObject(i+1, params[i]);
              }
      
              int updateRows = preparedStatement.executeUpdate();
      
              return updateRows;
          }
      
      
          //释放资源
          public static boolean closeResource(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet){
              boolean flag = true;
      
              if(resultSet != null){
                  try{
                      resultSet.close();
                      //GC回收
                      resultSet  = null;
                  }catch (SQLException e){
                      e.printStackTrace();
                      flag = false;
                  }
              }
      
              if(preparedStatement != null){
                  try{
                      preparedStatement.close();
                      //GC回收
                      preparedStatement = null;
                  }catch (SQLException e){
                      e.printStackTrace();
                      flag = false;
                  }
              }
      
              if(connection != null){
                  try{
                      connection.close();
                      //GC回收
                      connection = null;
                  }catch (SQLException e){
                      e.printStackTrace();
                      flag = false;
                  }
              }
      
              return flag;
          }
      }
      

      【注意】

      1. 参数名称一定要正确比配

      2. jdbc配置url要写对

        useSSL=true是进行安全验证,一般通过证书或者令牌什么的,useSSL=false就是通过账号密码进行连接,通常使用useSSL=false!!!

    4. 编写字符编码过滤器

  7. 导入静态资源

二、登录功能实现

  1. 编写前端页面

    login.jsp

    <div class="inputbox">
                        <label>用户名:</label>
    					<input type="text" class="input-text" id="userCode" name="userCode" placeholder="请输入用户名" required/>
    				</div>	
    				<div class="inputbox">
                        <label>密码:</label>
                        <input type="password" id="userPassword" name="userPassword" placeholder="请输入密码" required/>
                    </div>	
    
  2. 设置首页

    /jsp/frame.jsp

  3. 编写dao层登录用户登录的接口

    User baseDao(Connection connection, String userCode) throws SQLException
    
  4. 编写dao接口的实现类

    用类java.sql.Statement的executequery()方法查询的结果集永远不会返回null,可以用rs.next()方法来判断有没结果集。因为一个结果集最初将游标定位在第一行的前面,每调用一次,游标后移一个,当resultset游动到最后一行,再调用next()方法会返回false,并且游标也到了最后一行的后面!要是再调用next()的话就会出现异常!!!!!!

    • 输入connection、userCode
    • 编写sql语句,和参数params
    • 调用**baseDao(connection, sql, params, resultSet, preparedStatement)**的查询方法
    • 如果返回的resultSet有值:resulSet.next(), 生成一个user对象
    • 关闭prepareStatement和resultSet
    • 返回user
  5. 业务层接口

    • public User loginService(String userCode, String password);
      
  6. 业务层接口实现类

    • 生成connection对象,loginDao对象:loginDao(connection, userCode)
    • 利用loginDao返回的user对象的password参数与输入的password进行对比,如果不一样就代表登录信息出错,让user=null,交给上一层处理。
    • 关闭connection
  7. 编写Servlet层

    • 实例化UserServiceImpl

    • 使用userServiceImpl.loginService(userCode, password)方法,返回User对象

    • 判断user是否是null

      • 如果不是null,即查有此人,重定向到主页
      • 如果是null,即查无此人,转发回登录页面,并提示输入密码错误
      public class LoginServlet extends HttpServlet {
      
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      
              String userCode = req.getParameter("userCode");
              String password = req.getParameter("userPassword");
      
              UserService userService = new UserServiceImpl();
              User user = userService.loginService(userCode, password);
      
      
              if(user != null){//查有此人,可以登录
                  //将用户的信息放到Session中
                  req.getSession().setAttribute(Constants.USER_SESSION, user);//尽量放在一个常量里面
                  //跳转到内部主页
                  System.out.println("===============================查有此人");
                  resp.sendRedirect(req.getContextPath() + "/jsp/frame.jsp");
              }else{//查无此人,无法登录
                  //转发回登录页面,顺带提示它,用户名或密码错误
                  System.out.println("登录失败,回到登录页面");
                  req.setAttribute("error", "用户名或者密码不正确");
                  req.getRequestDispatcher("login.jsp").forward(req, resp);
      
              }
      
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                 doGet(req, resp);
          }
      }
      
  8. 注册Servlet

  9. 测试访问,确保以上功能成功!

三、登录功能优化

在这里插入图片描述

注销功能:

思路:

  1. 移出session,返回登录页面
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //移出用户的Session
        req.getSession().removeAttribute(Constants.USER_SESSION);
        //回到登录页面
        resp.sendRedirect("/login.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  1. 注册LogoutServlet
<servlet>
        <servlet-name>LogoutServelt</servlet-name>
        <servlet-class>com.duan.servlet.user.LogoutServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LogoutServelt</servlet-name>
        <url-pattern>/jsp/logout.do</url-pattern>
    </servlet-mapping>

登录拦截优化

如果直接输入url访问主界面,在不设置登录拦截下,由于没有判定session内容,可以直接登录到主界面。

这样是不允许的!

所以使用过滤器拦截登录:

  1. 将req和resp转换

  2. 从HttpServletRequest中提取Session信息,提取user

  3. 如果user是空,就直接冲定向至错误页面**(这里注意重定向的路径设置)**

    • 因为此请求URL路径是

      http://localhost:8080/smbms/jsp/frame.jsp
      

      所以在此请求路径下,响应重定向至error.jsp,除了用绝对路径外,

      可使用相对路径:…/error.jsp

      (因此,重定向要通过请求路径来判断)

public class SysFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        //过滤器从Session中获取用户
        User user = (User)request.getSession().getAttribute(Constants.USER_SESSION);

        if(user == null){
            System.out.println("用户已经被移除了,马上重定向到错误页面");
            //已经被移出/注销了,或者未登录
            System.out.println(request.getRequestURI());// 因为复制粘贴的是登登录主页的url进行登录,所以获取request的URI就是:/smbms/jsp/frame.jsp
     
            response.sendRedirect(request.getContextPath() + "/error.jsp");//"/error.jsp"不行
        }else{
            chain.doFilter(req, resp);
        }
    }

    public void destroy() {
    }
}
【注意】重定向路径问题!

在上面

四、密码修改

  1. 导入前端素材

    <li><a href="../jsp/pwdmodify.jsp">密码修改</a></li>
    

    【注意】调整好head.jsp中的url路径,使之能够成功跳转至pwdmodify.jsp

  2. 从底至上,编写dao、service、 servlet层代码

    dao

    public int updatePwd(Connection connection, int id, String password) throws SQLException {
        PreparedStatement preparedStatement = null;
        String sql = null;
        int res = 0;
    
        if(connection != null){
            sql = "update smbms_user set userPassword = ? where id = ?";
            Object[] params = {password, id};
            res = baseDao.execute(connection, sql, params, preparedStatement);
            baseDao.closeResource(null, preparedStatement, null);
        }
        return res;
    }
    
    

    service

    public boolean updatePwd(int id, String password) {
            Connection connection = null;
            boolean flag = false;
    
            try{
                connection = baseDao.getConnection();
                int res = userDao.updatePwd(connection, id, password);
                if(res > 0){//返回值大于零,成功修改了
                    flag = true;
                }
            }catch (SQLException e){
                e.printStackTrace();
            }finally {
                baseDao.closeResource(connection, null, null);
            }
    
            return flag;
        }
    

    servlet

    public void updatePwd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //从Session里获取id!
            Object o = req.getSession().getAttribute(Constants.USER_SESSION);
            String newpassword = req.getParameter("newpassword");
            boolean flag = false;
    
            //判断o是否存在 和 新的密码是否有效
            if(o != null && newpassword != null && newpassword.length() != 0){
                User user = (User)o;
                int id = user.getId();
                UserServiceImpl userService = new UserServiceImpl();
                System.out.println(newpassword);
                flag = userService.updatePwd(id, newpassword);
    
                //修改后的结果
                if(flag){
                    //修改成功,就清空当前Session信息。
                    req.setAttribute("message", "修改密码成功,请退出, 使用新的密码登录");
                    req.getSession().removeAttribute(Constants.USER_SESSION);
                }else{
                    //修改失败
                    req.setAttribute("message", "修改密码失败");
                }
            }else{
                req.setAttribute("message", "新密码有问题!");
            }
            req.getRequestDispatcher("pwdmodify.jsp").forward(req,resp);
        }
    

【注意】

  • servlet层注意在web.xml中进行url注册!

  • 实现servlet的复用

    利用前端中的input type=hidden, servlet读取其值,判断input需要的方法

【注意】Ajax技术
  • 请求方法GET
  • 请求路径url
  • 请求method在Servlet中读取该值而选择相应的方法,以及Ajax传递的参数,最终返回data
  • dataType:要求返回类型是json类型
    • 通过阿里巴巴的Fastjson来构造json格式的字符串,在resp中writer出去。

达到效果:旧密码的输入对错直接在前端通过Ajax技术来判断!而且直接能够当即显示对错

在这里插入图片描述

oldpassword.on("blur",function(){
    $.ajax({
        type:"GET",
        url:"/smbms/jsp/user.do",
        //url:path+"/jsp/user.do",
        data:{method:"pwdmodify",oldpassword:oldpassword.val()},	//Ajax传递的参数
        //path+/jsp/user.do?method=pwdmodify&oldpassword=oldpassword.val();
        dataType:"json",	//主流开发都是用JSON实现前后端交互
        success:function(data){
            if(data.result == "true"){//旧密码正确
                validateTip(oldpassword.next(),{"color":"green"},imgYes,true);
            }else if(data.result == "false"){//旧密码输入不正确
                validateTip(oldpassword.next(),{"color":"red"},imgNo + " 原密码输入不正确",false);
            }else if(data.result == "sessionerror"){//当前用户session过期,请重新登录
                validateTip(oldpassword.next(),{"color":"red"},imgNo + " 当前用户session过期,请重新登录",false);
            }else if(data.result == "error"){//旧密码输入为空
                validateTip(oldpassword.next(),{"color":"red"},imgNo + " 请输入旧密码",false);
            }
        },
        error:function(data){
            //请求出错
            validateTip(oldpassword.next(),{"color":"red"},imgNo + " 请求错误",false);
        }
    });


}).on("focus",function(){
    validateTip(oldpassword.next(),{"color":"#666666"},"* 请输入原密码",false);
});

五、用户管理实现

1. 获取用户数量

【重点】这里的SQL编写方法
  1. UserDao

  2. UserDaolmpl

    • 查询方法参数:connection、userName、userRole

在这里插入图片描述

 > 由于页面查询可以设置用户名、用户角色进行指定查询,所以后台查询也需要设置条件。
  • 用户信息栏中体现的信息不只是一个smbms_user表中的信息,而是联合了smbms_role中的信息,所以SQL需要写出联表查询

    select count(1) as count from smbms_user u,smbms_role r where u.userRole = r.id
    
  • 另外还需设置查询条件,即用户名、用户角色。

    由于不一定在查询条件中有输入用户名和用户角色,所以应该先进行判断,接收到的参数userName和userRole是否是空或是>0。根据不同的情况往sql中加入查询条件,以及往params中添加具体条件信息(这里需要进行模糊查询,有关姓名;所以我们的sql参数改用可以实时add元素的ArrayList的类型进行收集,最后再转换为数组,真的很方便)

    所以我们编写代码使得:如果加一个条件,对应加一个 SQL 以及 指定"?"的参数

    //1. 联表查询:查询 用户表中的userRole 等于 角色表中的角色id时 的所有行数!(因为页面列表中用户信息要显示用户角色名字)
    //"select count(1) as count from smbms_user u,smbms_role r where u.userRole = r.id";
    StringBuilder sql = new StringBuilder();
    sql.append("select count(1) as count from smbms_user u,smbms_role r where u.userRole = r.id");
    
    ArrayList<Object> list = new ArrayList<Object>();//存放我们的参数
    
    //2. 查询条件1:用户名
    if(!StringUtils.isNullOrEmpty(userName)){ //如过界面中输入了userName,则往SQL中加入新的查询条件,进行模糊查询
        sql.append("and u.userName like ?");
        list.add("%" + userName + "%"); //index=0
    }
    
    //3. 查询条件2:用户角色
    if(userRole > 0){
        sql.append("and u.userRole = ?");
        list.add(userRole); //index=1
    }
    
    System.out.println("UserDaoImpl -> numOfUser" + sql.toString());
    Object[] params = list.toArray();
    
    resultSet = baseDao.execute(connection, sql.toString(), params, resultSet, preparedStatement);
    
  1. UserService

  2. UserServiceImpl

2. 获取用户列表

【注意】SQL分页LIMIT使用方法
  1. UserDao

  2. UserDaoImpl

    这次的代码与上面查询用户数量的代码开始有大量重复

    主要添加了分页的代码:

    • 由于查询用户列表的方法参数多了 当前页currentPageNo、每页用户数pageSize这两个参数

    • 通过这两个参数要指定到表中具体查询的位置

      【比如】

      currentPageNo表中起始行开始pageSize行
      100 1 2 3 4
      255 6 7 8 9
      31010 11 12 13 14
      第n行(n-1) * pageSize从起始行开始pageSize行
    • 结合SQL中的LIMIT限定查询表达,两个参数下:

      1. 第一参数就是表中起始行:(currentPageNo-1)* pageSize
      2. 从起始行开始检索多少行: pageSize
      //条件3: 指定分页
      sql.append(" order by creationDate DESC limit ?,?");//DESC:降序
      
      //因为limit带2个值时:第一个数是开始位置,第二个数是要检索的行数(SQL中检索出来的第一行为行0,而不是行1)
      //输入的currenPageNo--------->页数
      //(currentPageNo - 1) * pageSize 后,currenPageNo等于页数对应表中的起始位置(行)
      currentPageNo = (currentPageNo - 1) * pageSize;
      list.add(currentPageNo); //要开始检索的位置
      list.add(pageSize); //从上述位置开始检索所少个
      
      System.out.println("sql ----- >" + sql.toString());//打印出来看看
      Object[] params = list.toArray();
      resultSet = baseDao.execute(connection, sql.toString(), params, resultSet, preparedStatement);
      
  3. UserService

  4. UserServiceImpl

    与获取用户数量的Service层变化不大

3. 获取角色列表

为了我们职责统一,可以把角色的操作单独放在一个包中和pojo对应

获取角色列表的原因是:在用户角色选择栏里有所有用户角色的信息

在这里插入图片描述

  1. UserDao

  2. UserDaoImpl

    读取角色表中的所有信息

    select * from smbms_role
    

    直接返回一个Role列表

    public List<Role> getRoleList(Connection connection) throws SQLException {
    
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List<Role> roleList = new ArrayList<Role>();
    
        if(connection != null){
            String sql = "select * from smbms_role";
            Object [] params = {};
    
            resultSet = baseDao.execute(connection, sql, params, resultSet, preparedStatement);
    
            while(resultSet.next()){
                Role role = new Role();
                role.setId(resultSet.getInt("id"));
                role.setRoleCode(resultSet.getString("roleCode"));
                role.setRoleName(resultSet.getString("roleName"));
                roleList.add(role);
            }
            baseDao.closeResource(null, preparedStatement, resultSet);
        }
        return roleList;
    }
    
  3. UserService

  4. UserServiceImpl

4. 用户显示的Servlet

  1. 获取用户前端的数据(查询)
  2. 判断请求是否需要执行,看参数的值判断
  3. 为了实现分页,需要计算出当前页面和总页面,页面大小
  4. 用户列表展示
  5. 返回前端
//重点、难点
public void query(HttpServletRequest req, HttpServletResponse resp){

    //从前端获取数据
    String queryUserName = req.getParameter("queryname");
    String temp = req.getParameter("queryUserRole");
    String pageIndex = req.getParameter("pageIndex");
    int queryUserRole = 0;//刚进入页面时没有选择用户角色条件,默认为0

    //实例化ServiceImpl
    UserServiceImpl userService = new UserServiceImpl();

    //第一次走这个请求,一定是第一页,页面大小是固定的,所以先给默认值
    int pageSize = Constants.pageSize;//设置页面容量
    int currentPage = 1;//当前页码

    System.out.println("queryUserName servlet--------"+queryUserName);
    System.out.println("queryUserRole servlet--------"+queryUserRole);
    System.out.println("query pageIndex--------- > " + pageIndex);

    //根据前端输入,再修改默认值
    if(queryUserName == null){
        queryUserName = "";//一开始没有输入用户名,默认为""
    }
    if(temp != null && !temp.equals("")){
        queryUserRole = Integer.parseInt(temp); //给查询赋值! 0,1,2,3
    }
    if(pageIndex != null){
        currentPage = Integer.parseInt(pageIndex);
    }


    //获取用户总人数(分页: 上一页、下一页)
    int userCount = userService.getUserCount(queryUserName, queryUserRole);
    //实例化分页对象
    PageSupport pageSupport = new PageSupport();
    pageSupport.setCurrentPageNo(currentPage);
    pageSupport.setPageSize(pageSize);
    pageSupport.setTotalCount(userCount);

    //获取总页数
    int pageTotalPageCount = pageSupport.getTotalPageCount();

    //控制首页和尾页
    //如果页面小于1,就显示第一页的东西
    if(currentPage < 1){
        currentPage = 1;
    }else if(currentPage > pageTotalPageCount){//如果当前页面大于最后一页:
        currentPage = pageTotalPageCount;
    }

    //获取当页所有用户列表
    List<User> userList = userService.getUserList(queryUserName, queryUserRole, currentPage, pageSize);
    for (User user : userList) {
        System.out.println(user.getUserName());
    }
    req.setAttribute("userList", userList);
    //获去所有用户角色信息
    RoleServiceImpl roleService = new RoleServiceImpl();
    List<Role> roleList = roleService.getRoleList();
    req.setAttribute("roleList", roleList);

    req.setAttribute("totalCount", userCount);
    req.setAttribute("currentPageNo", currentPage);
    req.setAttribute("totalPageCount", pageTotalPageCount);


    //返回前端
    try{
        req.getRequestDispatcher("userlist.jsp").forward(req, resp);
    }catch (ServletException e){
        e.printStackTrace();
    }catch (IOException e){
        e.printStackTrace();
    }

}

5. 增加用户

dao层:注意SQL的insert写法

public int insertUser(Connection connection, User user) throws SQLException {
    PreparedStatement preparedStatement = null;
    int res = 0;

    if(connection != null && user != null){
        String sql = "insert into smbms_user (userCode, userName, userPassword, gender, birthday, phone, address, userRole, creationDate, createdBy) values(?,?,?,?,?,?,?,?,?,?)";
        String userCode = user.getUserCode();
        String userName = user.getUserName();
        String userPassword = user.getUserPassword();
        int gender = user.getGender();
        Date birthday = user.getBirthday();
        String phone = user.getPhone();
        String address = user.getAddress();
        int userRole = user.getUserRole();
        Date creationDate = user.getCreationDate();
        Integer createdBy = user.getCreatedBy();

        Object []params = {userCode, userPassword, gender, birthday, phone, address, userRole, creationDate, createdBy};

        res = baseDao.execute(connection, sql, params, preparedStatement);

        baseDao.closeResource(null, preparedStatement, null);
    }

    return res;
}

Service层:

【注意】JDBC事务管理、返回值类型定位boolean类型(是否成功add)

public boolean insertUser(User user) {
    Connection connection = null;
    boolean flag = false;


    try{
        connection = baseDao.getConnection();
        connection.setAutoCommit(false);//开启JDBC事务管理
        int res = userDao.insertUser(connection, user);

        connection.commit();

        if(res > 0){
            flag = true;
            System.out.println("add success!");
        }else{
            System.out.println("add failed!");
        }
    }catch (SQLException e){
        e.printStackTrace();
        try{
            System.out.println("rollback==================");
            connection.rollback();
        }catch (SQLException e1){
            e1.printStackTrace();
        }
    }finally{
        baseDao.closeResource(connection, null, null);
    }

    return flag;
}

Servlet层

【注意】

  1. birthday字符串到Date类型的转换方式
public void add(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
    String userName = req.getParameter("userName");
    String userCode = req.getParameter("userCode");
    String userPassword = req.getParameter("userPassword");
    String gender = req.getParameter("gender");
    String birthday = req.getParameter("birthday");
    String phone = req.getParameter("phone");
    String address =req.getParameter("address");
    String userRole = req.getParameter("userRole");

    User user = new User();
    user.setUserCode(userCode);
    user.setUserName(userName);
    user.setUserPassword(userPassword);
    user.setGender(Integer.parseInt(gender));

    //获得SimpleDateFormat类,我们转换为yyyy-MM-dd的时间格式
    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
    try{
        //使用SimpleDateFormat的parse()方法生成Date
        Date date = sf.parse(birthday);
        user.setBirthday(date);
    }catch (ParseException e){
        e.printStackTrace();
    }

    user.setPhone(phone);
    user.setAddress(address);
    user.setUserRole(Integer.parseInt(userRole));
    user.setCreationDate(new Date());
    user.setCreatedBy(((User)req.getSession().getAttribute(Constants.USER_SESSION)).getId());

    UserServiceImpl userService = new UserServiceImpl();
    if(userService.insertUser(user)){
        System.out.println("保存成功");
        resp.sendRedirect(req.getContextPath() + "/jsp/user.do?method=query");
    }else {
        System.out.println("保存失败");
        req.getRequestDispatcher("useradd.jsp").forward(req, resp);
    }

}
【注意】重定向url问题

保存成功,重定向至req.getContextPath() + "/jsp/user.do?method=query",而不是到req.getContextPath() + "/jsp/userlist.jsp"

可能是应为,直接跳转到jsp页面,并没有触发到form表单的action,所以跳转到的界面没有用户列表显示。

1、 userlist.jsp中提交表单时发送url为:req.getContextPath() + "/jsp/user.do?method=query",即提交表单时向此url发送表单数据。而此form没有submit提交键,而是从head.jsp中<a href…触发提交(提交userlist.jsp的表单),进而进入Servlet进行处理后返回userlist.jsp,此时用户信息就显示出来了。

在这里插入图片描述

2、 由1可知,重定向到req.getContextPath() + "/jsp/user.do?method=query"就可以完成form表单的提交,Servlet提取到后台信息,在重定向至userlist.jsp。就可以跳转到右用户信息的表单了。

测试时遇见问题:

(前端)用户添加页面

【注意】用户角色一栏弹不出选项?

起初以为是jsp中没有配置,而roleLIst已经在js中配置过了,js中的method=getrolelist 。所以原因是发现到了Servlet中买有写获取角色列表的方法,导致js中的ajax请求在后端拿不到rolelist信息,所以最后其补充。

js:

/*获取rolelist*/
$.ajax({
    type:"GET",//请求类型
    url:path+"/jsp/user.do",//请求的url
    data:{method:"getrolelist"},//请求参数
    dataType:"json",//ajax接口(请求url)返回的数据类型
    success:function(data){//data:返回数据(json对象)
        if(data != null){
            userRole.html("");
            var options = "<option value=\"0\">请选择</option>";
            for(var i = 0; i < data.length; i++){
                //alert(data[i].id);
                //alert(data[i].roleName);
                options += "<option value=\""+data[i].id+"\">"+data[i].roleName+"</option>";
            }
            userRole.html(options);
        }
    },
    error:function(data){//当访问时候,404,500 等非200的错误状态码
        validateTip(userRole.next(),{"color":"red"},imgNo+" 获取用户角色列表error",false);
    }
});

userServlet:

//获取角色列表
private void getrolelist(HttpServletRequest req, HttpServletResponse resp) {

    RoleServiceImpl roleService = new RoleServiceImpl();
    List<Role> roleList = null;
    roleList = roleService.getRoleList();

    resp.setContentType("application/json");
    try{
        PrintWriter writer = resp.getWriter();
        writer.write(JSONArray.toJSONString(roleList));
        System.out.println(JSONArray.toJSONString(roleList));
        writer.flush();
        writer.close();
    }catch (IOException e){
        e.printStackTrace();
    }
}
【注意】将list转换为json的方式

【注意】提交保存时,没有反应。

控制台报错:

在这里插入图片描述

可知是userCode信息输入的问题

经查到定位到问题错在处:

在这里插入图片描述

访问url相当于: //path + /jsp/user.do?method=ucexist&userCode=userCode.val();

前端通过ajax技术使用userCode查询数据库中已有同样userCode的用户数量,如果数量>0,就代表已经该userCode已经使用过了,并前端给予提示。

Servlet:

响应类型得用ajax指定的json类型返回!

//判断用户账号是否可用
public void userCodeExist(HttpServletRequest req, HttpServletResponse resp){
    String userCode = req.getParameter("userCode");
    User user = null;

    Map<String, String> map = new HashMap<String, String>();
    if(StringUtils.isNullOrEmpty(userCode)){
        map.put("userCode", "exist");
    }else{
        UserServiceImpl userService = new UserServiceImpl();
        user = userService.selectUserCodeExist(userCode);
        if(user != null){
            map.put("userCode", "exist");
        }else {
            map.put("userCode", "noexist");
        }
    }
    try{
        resp.setContentType("application/json");
        PrintWriter writer = resp.getWriter();
        writer.write(JSONArray.toJSONString(map));
        writer.flush();
        writer.close();
    }catch (IOException e){
        e.printStackTrace();
    }
}

6. 删除用户

  1. 找到前端代码

    <span><a class="deleteUser" href="javascript:;" userid=${user.id } username=${user.userName }><img src="${pageContext.request.contextPath }/images/schu.png" alt="删除" title="删除"/></a></span>
    
    function deleteUser(obj){
        $.ajax({
            type:"GET",
            url:path+"/jsp/user.do",
            data:{method:"deluser",uid:obj.attr("userid")},
            dataType:"json",
            success:function(data){
                if(data.delResult == "true"){//删除成功:移除删除行
                    cancleBtn();
                    obj.parents("tr").remove();
                }else if(data.delResult == "false"){//删除失败
                    //alert("对不起,删除用户【"+obj.attr("username")+"】失败");
                    changeDLGContent("对不起,删除用户【"+obj.attr("username")+"】失败");
                }else if(data.delResult == "notexist"){
                    //alert("对不起,用户【"+obj.attr("username")+"】不存在");
                    changeDLGContent("对不起,用户【"+obj.attr("username")+"】不存在");
                }
            },
            error:function(data){
                //alert("对不起,删除失败");
                changeDLGContent("对不起,删除失败");
            }
    
  2. 在UserServlet中编写deleteUser方法

public void deleteUser(HttpServletRequest req, HttpServletResponse resp){
    String userid = req.getParameter("uid");
    int id = 0;
    id = Integer.parseInt(userid);

    Map<String, String> map = new HashMap<String, String>();
    if(id <= 0){
        map.put("delResult", "notexist");
    }else{
        UserServiceImpl userService = new UserServiceImpl();
        if(userService.deleteUser(id)){
            map.put("delResult", "true");
            System.out.println("删除完成!");
        }else{
            map.put("delResult","false");
            System.out.println("删除失败!");
        }
    }

    try{
        resp.setContentType("application/json");
        PrintWriter writer = resp.getWriter();
        writer.write(JSONArray.toJSONString(map));
    }catch (IOException e){
        e.printStackTrace();
    }

}

7. 修改用户信息

前端页面:红圈按钮即为修改案件

在这里插入图片描述

对应userlist.jsp文件中的这串代码:

<span><a class="modifyUser" href="javascript:;" userid=${user.id } username=${user.userName }><img src="${pageContext.request.contextPath }/images/xiugai.png" alt="修改" title="修改"/></a></span>

userlist.js中:

$(".modifyUser").on("click",function(){
    var obj = $(this);
    window.location.href=path+"/jsp/user.do?method=modify&uid="+ obj.attr("userid");
});

触发访问资源路径url:path +"/jsp/user.do?method=modify&uid=userid"

对应servlet如下:

Servlet中选用getUserById方法获取id指定的用户信息,最终将user保存到请求域中

.....
}else if(method != null && method.equals("modify")){
    this.getUserById(req, resp, "usermodify.jsp");
}
.....
    
    
    
public void getUserById(HttpServletRequest req, HttpServletResponse resp, String url) throws ServletException, IOException {
    String id = req.getParameter("uid");

    if(!StringUtils.isNullOrEmpty(id)){
        //调用后台方法得到user对象
        UserService userService = new UserServiceImpl();
        User user = userService.selectUserById(Integer.parseInt(id));
        req.setAttribute("user", user);
        req.getRequestDispatcher(url).forward(req, resp);//获取到要修改的用户,跳转到usermodify.jsp界面。
    }
}

跳转到usermodify.jsp去执行修改操作,usermodify.jsp页面中起初显示要修改用户的每项信息,在其上修改即可。

在这里插入图片描述

usermodify.jsp中的form表单action直接跳转至Servlet中,method的value是modifyexe,对应Servlet中的modify方法。通过此方法来进行修改操作。

Servelt:

//修改用户信息
public void modify(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
    String id = req.getParameter("uid");
    String userName = req.getParameter("userName");
    String gender = req.getParameter("gender");
    String birthday = req.getParameter("birthday");
    String phone = req.getParameter("phone");
    String address = req.getParameter("address");
    String userRole = req.getParameter("userRole");

    System.out.println("我读取到了信息");

    User user = new User();
    user.setId(Integer.parseInt(id));
    user.setUserName(userName);
    user.setGender(Integer.parseInt(gender));
    try{
        user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(birthday));
    }catch (ParseException e){
        e.printStackTrace();
    }
    user.setPhone(phone);
    user.setAddress(address);
    user.setUserRole(Integer.parseInt(userRole));
    user.setModifyBy(((User)(req.getSession().getAttribute(Constants.USER_SESSION))).getId());
    user.setModifyDate(new Date());

    System.out.println("我准备将user信息发送到Service层");

    UserServiceImpl userService = new UserServiceImpl();
    if (userService.modifyUser(user)) {
        resp.sendRedirect(req.getContextPath() + "/jsp/user.do?method=query");
    }else{
        req.getRequestDispatcher("usermodify.jsp").forward(req, resp);
    }
}

Service:

//修改用户信息
public boolean modifyUser(User user) {
    Connection connection = null;
    int res = 0;
    boolean flag = false;

    try{
        connection = baseDao.getConnection();
        res = userDao.modify(connection, user);

        if(res > 0){
            flag = true;
        }

    }catch (Exception e){
        e.printStackTrace();
    }finally{
        baseDao.closeResource(connection, null, null);
    }

    return flag;
}

Dao:

public int modify(Connection connection, User user) throws Exception {
    // TODO Auto-generated method stub
    int flag = 0;
    PreparedStatement pstm = null;
    if(null != connection){
        String sql = "update smbms_user set userName=?,"+
            "gender=?,birthday=?,phone=?,address=?,userRole=?,modifyBy=?,modifyDate=? where id = ? ";
        Object[] params = {user.getUserName(),user.getGender(),user.getBirthday(),
                           user.getPhone(),user.getAddress(),user.getUserRole(),user.getModifyBy(),
                           user.getModifyDate(),user.getId()};
        flag = baseDao.execute(connection, sql, params, pstm);
        baseDao.closeResource(null, pstm, null);
    }
    return flag;
}
【注意】前端接口的作用和其跳转去向,以及其所对接的后端接口处理功能。

modifyUser(User user) {
Connection connection = null;
int res = 0;
boolean flag = false;

try{
    connection = baseDao.getConnection();
    res = userDao.modify(connection, user);

    if(res > 0){
        flag = true;
    }

}catch (Exception e){
    e.printStackTrace();
}finally{
    baseDao.closeResource(connection, null, null);
}

return flag;

}


Dao:

```java
public int modify(Connection connection, User user) throws Exception {
    // TODO Auto-generated method stub
    int flag = 0;
    PreparedStatement pstm = null;
    if(null != connection){
        String sql = "update smbms_user set userName=?,"+
            "gender=?,birthday=?,phone=?,address=?,userRole=?,modifyBy=?,modifyDate=? where id = ? ";
        Object[] params = {user.getUserName(),user.getGender(),user.getBirthday(),
                           user.getPhone(),user.getAddress(),user.getUserRole(),user.getModifyBy(),
                           user.getModifyDate(),user.getId()};
        flag = baseDao.execute(connection, sql, params, pstm);
        baseDao.closeResource(null, pstm, null);
    }
    return flag;
}
【注意】前端接口的作用和其跳转去向,以及其所对接的后端接口处理功能。

我只完成了用户功能方面,以此练习自己的Servlet能力。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SMBMS数据库代码是指《超市管理系统》的数据库代码,该代码主要用于实现超市的管理功能,包括商品信息管理、供应商管理、用户管理、订单管理和库存管理等。 首先,我们需要创建相应的数据库和数据表。数据库中包含商品信息表、供应商表、用户表和订单表等,每个表都有对应的字段,用于存储相关的信息。 其次,我们需要编写相应的代码来实现具体的功能。比如,对于商品信息管理,我们可以编写代码来实现商品的增加、删除、修改和查询等功能。对于供应商管理,我们可以编写代码来实现供应商的添加、删除、修改和查询等功能。对于用户管理,我们可以编写代码来实现用户的注册、登录、修改密码和权限管理等功能。对于订单管理,我们可以编写代码来实现订单的添加、删除、修改和查询等功能。对于库存管理,我们可以编写代码来实现库存的更新、查询和报警等功能。 最后,我们需要将代码与数据库连接起来,即通过数据库操作的相关函数来实现数据的读取和更新等。同时,我们还需要考虑数据的安全性和完整性,比如通过加密算法对用户密码进行加密存储,以保护用户信息的安全。 综上所述,SMBMS数据库代码是超市管理系统的数据库代码,通过编写相应的代码和实现数据库的连接,可以实现超市的管理功能,包括商品信息管理、供应商管理、用户管理、订单管理和库存管理等。这些功能可以帮助超市提高管理效率、提升服务质量,从而更好地满足客户的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值