项目实战系列三: 家居购项目第二部分

🐇servlet合并

增加隐藏域

合并到MemberServlet

🍎反射+模板设计模式+动态代理

新建BasicServlet类, 继承HttpServlet

java 复制代码
public class BasicServlet extends HttpServlet {
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
    
	@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String action = req.getParameter("action");
        try {
            //1.得到子类对应的class对象
            Class<? extends BasicServlet> aClass = this.getClass();
            //2.创建对象
            Object o = aClass.newInstance();
            //3.得到action方法对象
            Method declaredMethod = this.getClass()
                    .getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
            declaredMethod.invoke(o, req, resp);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

子类中没有doGet, doPost方法, 会调用父类的doGet, doPost.

🌳显示家居

需求分析

  1. 给后台管理提供独立登陆页面 manage_login.jsp(已提供)

  2. 管理员(admin表)登陆成功后, 显示管理菜单页面

  3. 管理员点击家居管理, 显示所有家居信息
    程序框架图

  4. 页面准备

  5. 新建admin表 👉 参考member表
    新建furn表

  6. 新建Admin实体类
    新建Furn实体类(无参构造器与set方法底层反射用, get方法前端EL表达式用)

  7. 书写AdminDAO, AdminDAOImpl, 并测试; 书写AdminService, AdminServiceImpl, 并测试 👉 参考Member
    书写FurnDAO, FurnDAOImpl 👉 并测试

  8. 书写FurnService, FurnServiceImpl 👉 并测试

  1. 接通web层
    管理员登录Servlet
java 复制代码
public class AdminServlet extends BasicServlet {
    private AdminService adminService = new AdminServiceImpl();

    protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        Admin admin = new Admin(null, username, password, null);

        if (adminService.login(admin)) {
            //管理员登录成功
            request.getRequestDispatcher("/views/manage/manage_menu.jsp")
                    .forward(request, response);
        } else {
            System.out.println("登陆失败, 返回登陆页面");
            request.setAttribute("username", username);
            request.setAttribute("msg", "用户名或密码不正确");
            request.getRequestDispatcher("/views/manage/manage_login.jsp")
                    .forward(request, response);
        }
    }
}

家居显示Servlet

xml 复制代码
<servlet>
        <servlet-name>FurnServlet</servlet-name>
        <servlet-class>com.zzw.furn.web.FurnServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FurnServlet</servlet-name>
        <url-pattern>/manage/furnServlet</url-pattern>
    </servlet-mapping>
java 复制代码
public class FurnServlet extends BasicServlet {
    private FurnService furnService = new FurnServiceImpl();

    protected void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Furn> furns = furnService.queryFurn();
        //将结果保存到request域
        request.setAttribute("furns", furns);
        //请求转发到管理家具页面
        request.getRequestDispatcher("/views/manage/furn_manage.jsp")
                .forward(request, response);
    }
}
  1. 前端页面
    manage_login.jsp, 管理员登录页面
html 复制代码
<span class="errorMsg"
      style="float: right; font-weight: bold; color: lightgray; font-size: 20pt; margin-left: 10px;">${msg}</span>
<%--管理员登陆--%>
<form action="adminServlet" method="post">
    <input type="hidden" name="action" value="login"/>
    <input type="text" name="username" value="${username}" placeholder="Username"/>
    <input type="password" name="password" placeholder="Password"/>
    <div class="button-box">
        <div class="login-toggle-btn">
            <input type="checkbox"/>
            <a class="flote-none" href="javascript:void(0)">Remember me</a>
            <a href="#">Forgot Password?</a>
        </div>
        <button type="submit"><span>Login</span></button>
    </div>
</form>

manage_menu.jsp, 家居菜单页面

furn_manage.jsp, 家居显示页面

<c:forEach items="${requestScope.furns}" var="furn"> items里用EL表达式括起来, var里不用EL表达式

🌳添加家居

思路分析

  1. 请求添加家居, 请求FurnServlet的add方法, 将前端提交的数据封装到Furn对象
  2. 调用FurnService.add(Furn furn)方法
  3. 跳转到显示家居的页面
    程序框架图
  4. FurnDAO
  5. FurnService
  1. web层
    FurnServlet
java 复制代码
protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        String business = req.getParameter("business");
        BigDecimal price = new BigDecimal(req.getParameter("price"));
        int saleNum = DataUtils.parseInt(req.getParameter("saleNum"), 0);
        int inventory = DataUtils.parseInt(req.getParameter("inventory"), 0);

        Furn furn = new Furn(null, name,
                business, price, saleNum, inventory, "...");

        if (furnService.add(furn) > 0) {
            System.out.println("添加成功, 请求转发到list");
            //req.getRequestDispatcher("/manage/furnServlet?action=list")
            //        .forward(req, resp);
            resp.sendRedirect(req.getContextPath() + "//manage/furnServlet?action=list");
        } else {
            System.out.println("添加失败, 返回到添加页面");
            req.getRequestDispatcher("views/manage/furn_add.jsp")
                    .forward(req, resp);
        }
    }

解决中文乱码问题

  1. 前端: furn_manage跳转到添加家居页面
html 复制代码
<!-- Single Wedge Start -->
<div class="header-bottom-set dropdown">
    <a href="views/manage/furn_add.jsp">添加家居</a>
</div>

添加furn_add.jsp

html 复制代码
<!--添加在tr标签的下一行-->
<span class="errorMsg"
      style="float: right; font-weight: bold; color: lightgray; font-size: 20pt; margin-left: 10px;"></span>


🍉解决重复添加

请求转发, 当用户刷新页面时, 会重新发出第一次的请求, 造成数据重复提交

解决方案: 使用重定向

🍉后端数据校验说明

后端方案一
后端方案二

前端数据校验

js 复制代码
$(":submit").click(function () {
    var price = $("input[name='price']").val();
    var saleNum = $("input[name='saleNum']").val();
    var inventory = $("input[name='inventory']").val();

    //价格 非零开头最多两位小数
    var priceRegExp = /^[1-9]\d*(\.\d{1,2})?$/;
    if (!priceRegExp.test(price)) {
        $("span.errorMsg").text("价格格式不对");
        return false;
    }

    //销量 非零开头正整数
    var saleNumRegExp = /^0$|^[1-9]\d*$/;
    if (!saleNumRegExp.test(saleNum)) {
        $("span.errorMsg").text("销量格式不对");
        return false;
    }
    //库存 非零开头正整数
    var inventoryRegExp = /^0$|^[1-9]\d*$/;
    if (!inventoryRegExp.test(inventory)) {
        $("span.errorMsg").text("库存格式不对");
        return false;
    }
})

🍉BeanUtils自动封装Bean

引入: commons-logging-1.1.1.jar, commons-beanutils-1.8.0.jar

  1. 使用BeanUtils自动封装javabean
java 复制代码
protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //这里我们使用第二种方式, 将前端提交的数据, 自动封装成Furn的Javabean对象
        //使用beanUtils完成javabean对象的自动封装
        Furn furn =
                DataUtils.copyParamToBean(req.getParameterMap(), new Furn());

        if (furnService.addFurn(furn)) {
            String pageNo = req.getParameter("pageNo");
            System.out.println("添加成功..");
            //req.getRequestDispatcher("/manage/furnServlet?action=list").forward(req, resp);
            resp.sendRedirect(req.getContextPath() + "/manage/furnServlet?action=list");
        } else {
            System.out.println("添加失败");
            req.setAttribute("errorMsg", "添加失败");
            req.getRequestDispatcher("/views/manage/furn_add.jsp").forward(req, resp);
        }
    }

debug小技巧👉

  1. 报错
    原因: 由于前端没有传imagePath的字段, 所以后端在构建furn对象的时候, imagePath属性位null
    解决方案 👇
  1. 将 把数据自动封装成JavaBean的功能封装到工具类
java 复制代码
public class DataUtils {
   //将方法, 封装到静态方法, 方便使用
   public static <T> T copyParamToBean(Map value, T bean) {
       try {
           BeanUtils.populate(bean, value);
       } catch (Exception e) {
           throw new RuntimeException(e);
       }
       return bean;
   }
}

调用

🌳删除家居

需求分析

  1. 管理员进入到家居管理页面
  2. 点击删除家居链接, 弹出确认窗口, 确认-删除, 取消-放弃
    程序框架图
  3. FurnDAO
  4. FurnService
  1. web层 - FurnServlet
java 复制代码
protected void del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        int id = DataUtils.parseInt(req.getParameter("id"), 0);

        if (furnService.deleteFurnById(id) > 0) {
            System.out.println("删除成功");
        } else {
            System.out.println("删除失败");
        }
        
        resp.sendRedirect(req.getContextPath() + "/manage/furnServlet?action=list");
    }
  1. furn_manage.jsp页面
html 复制代码
<a furnName="${furn.name}" href="manage/furnServlet?action=del&id=${furn.id}">
    <i class="icon-close"></i>
</a>

jQuery操作父元素, 兄弟元素, 子元素, 请移步👉
js弹框请移步👉

js 复制代码
$("a[furnName]").click(function () {
    var furnName = $(this).attr("furnName");

    //js弹框
    //1.window.confirm 方法会弹出一个确认窗口
    //2.点击确定, 返回true
    //3.点击取消, 返回false
    var b = window.confirm("你确认要删除 " + furnName+ " 家居信息吗?");
    if (!b) {
        return false;
    }
    //简便写法
    return window.confirm("你确认要删除 " + furnName+ " 家居信息吗?");

    //最终写法
    return confirm("你确定要删除 " + furnName + " 家居信息嘛?");
});

🌳修改家具

思路分析

  1. 管理员进入家居管理页面furn_manage.jsp
  2. 点击修改家居链接, 回显该家居信息 furn_update.jsp
  3. 填写新的信息, 点击修改家居按钮
  4. 修改成功后, 显示刷新后的家居列表
    程序框架图
  5. FurnDAO

  6. FurnService

  1. web层 - FurnServlet
java 复制代码
protected void display(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        int id = DataUtils.parseInt(req.getParameter("id"), 0);

        Furn furn = furnService.queryFurnById(id);
        if (furn != null) {
            //将furn对象放入request域
            req.setAttribute("furn", furn);
            req.getRequestDispatcher("/views/manage/furn_update.jsp")
                    .forward(req, resp);
        } else {
            System.out.println("查询不到该信息");
            req.getRequestDispatcher("/views/manage/furn_manage.jsp")
                    .forward(req, resp);
        }
    }
java 复制代码
protected void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Furn furn =
                DataUtils.copyParamToBean(req.getParameterMap(), new Furn());

        if (furnService.updateFurn(furn) > 0) {
            System.out.println("更新成功");
            resp.sendRedirect(req.getContextPath() + "/manage/furnServlet?action=list");
        } else {
            req.setAttribute("msg", "更新失败");
            req.getRequestDispatcher("/manage/furnServlet?action=display")
                    .forward(req, resp);
        }
    }
  1. 前端
    furn_manage.jsp 点击修改,发出请求
html 复制代码
<a href="manage/furnServlet?action=display&id=${furn.id}">
    <i class="icon-pencil"></i>
</a>

在tr标签下面添加span标签

html 复制代码
<span class="errorMsg"
      style="float: right; font-weight: bold; color: lightgray; font-size: 20pt; margin-left: 10px;">${msg}</span>

furn_update.jsp 数据校验

js 复制代码
$(":submit").click(function () {
    var price = $("input[name='price']").val();
    var saleNum = $("input[name='saleNum']").val();
    var inventory = $("input[name='inventory']").val();

    //价格 非零开头最多两位小数
    var priceRegExp = /^[1-9]\d*(\.\d{1,2})?$/;
    if (!priceRegExp.test(price)) {
        $("span.errorMsg").text("价格格式不对");
        return false;
    }

    //销量 非零开头正整数
    var saleNumRegExp = /^0$|^[1-9]\d*$/;
    if (!saleNumRegExp.test(saleNum)) {
        $("span.errorMsg").text("销量格式不对");
        return false;
    }
    //库存 非零开头正整数
    var inventoryRegExp = /^0$|^[1-9]\d*$/;
    if (!inventoryRegExp.test(inventory)) {
        $("span.errorMsg").text("库存格式不对");
        return false;
    }
})

修改数据,点击提交

相关推荐
小树苗1931 天前
DePIN潜力项目Spheron解读:激活闲置硬件,赋能Web3与AI
人工智能·web3
CESS_Cloud1 天前
CESS 出席华盛顿区块链政策峰会:参与国家安全与数据隐私保护专题讨论
安全·阿里云·web3·去中心化·区块链
我可是千机伞2 天前
BOB.meme已于12月18日正式部署于BNB Chain
web3
TianXuan_Chain3 天前
web3跨链桥协议-Nomad
web3·区块链·智能合约·跨链桥
黑客老陈4 天前
蓝队HW初级面试题总结
服务器·网络·安全·小程序·web3
TinTin Land4 天前
Electric Capital 2024 年开发者报告 | 洞见未来 Web3 生态发展方向
web3
TechubNews4 天前
IntoTheBlock 联创:Web3 基础设施正在被过度建设,我们正在盲目行事
web3·区块链
Roun34 天前
探索Web3的核心原则:去中心化与用户控制
web3·去中心化·区块链
dingzd955 天前
Web3 时代:技术变革与未来展望
web3·去中心化·区块链·互联网
清 晨5 天前
Web3应用的未来:智能合约如何推动自动化变革
自动化·web3·智能合约