day11-功能实现10
家居网购项目实现010
以下皆为部分代码,详见 https://github.com/liyuelian/furniture_mall.git
24.bugFix-添加购物车按钮动态处理
24.1需求分析/图解
- 如某个家居的库存量为0,前台的“add to cart”按钮显示为“暂时缺货”
- 后台也要求添加校验,只有在库存>0时,才能添加到购物车
24.2代码实现
-
修改customer/index.jsp
-
CartServlet添加判断,如果在添加购物车时,该家居库存为0,就停止业务
24.3完成测试

25.功能23-附加功能-订单管理
25.1需求分析/图解
点击订单管理,前往order.jsp页面进行订单管理

点击详情的眼睛图标,可以显示该订单详情,即显示某个订单的所有订单项


25.2思路分析
点击订单管理按钮,跳转到订单管理页面order.jsp。根据用户id,在订单管理页面中显示用户对应的订单。点击订单详情,跳转到order_detail.jsp中,根据订单号显示订单所有项。
25.3代码实现
25.3.1dao层
OrderDAO
/** * 根据用户id,查询该用户的所有订单Order * * @param id 用户id * @return 返回订单 */ public List<Order> queryOrderByMemberId(int id);
OrderDAOImpl
@Override public List<Order> queryOrderByMemberId(int id) { String sql = "SELECT `id`,`create_time` AS createTime,`price`,`status`,`member_id` AS memberId " + "FROM `order` " + "WHERE `member_id`=?"; return queryMulti(sql, Order.class, id); }
test包-OrderDAOImplTest
@Test public void queryOrderByMemberId() { List<Order> orders = orderDAO.queryOrderByMemberId(2); for (Order order : orders) { System.out.println(order); } }

OrderItemDAO
/** * 根据订单id-orderId查询对应的表单项orderItem * * @param orderId 订单id * @return 返回表单项orderItem */ public List<OrderItem> queryOrderItemByOrderId(String orderId);
OrderItemDAOImpl
@Override public List<OrderItem> queryOrderItemByOrderId(String orderId) { String sql = "SELECT `id`,`name`,`price`,`count`,`total_price` AS totalPrice,`order_id` AS orderId " + "FROM `order_item` " + "WHERE `order_id`=?"; return queryMulti(sql, OrderItem.class, orderId); }
OrderItemDAOImplTest
@Test public void queryOrderItemByOrderId() { List<OrderItem> orderItems = orderItemDAO.queryOrderItemByOrderId("16722358644142"); for (OrderItem orderItem : orderItems) { System.out.println(orderItem); } }
25.3.2service层
OrderService
/** * 根据用户id返回订单order * @param id 用户id * @return 订单 */ public List<Order> queryOrderByMemberId(int id); /** * 根据订单id返回对应的订单项orderItem * @param orderId 订单id * @return 返回订单项 */ public List<OrderItem> queryOrderItemByOrderId(String orderId);
OrderServiceImpl
@Override public List<Order> queryOrderByMemberId(int id) { return orderDAO.queryOrderByMemberId(id); } @Override public List<OrderItem> queryOrderItemByOrderId(String orderId) { return orderItemDAO.queryOrderItemByOrderId(orderId); }
test包-OrderServiceImpl
@Test public void queryOrderByMemberId() { List<Order> orders = orderService.queryOrderByMemberId(3); for (Order order : orders) { System.out.println(order); } } @Test public void queryOrderItemByOrderId() { List<OrderItem> orderItems = orderService.queryOrderItemByOrderId("16722370522643"); for (OrderItem orderItem : orderItems) { System.out.println(orderItem); } }


25.3.3web层
OrderServlet,增加两个方法
/** * 显示订单order * * @param req * @param resp * @throws ServletException * @throws IOException */ protected void showOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取当前用户id Member member = (Member) req.getSession().getAttribute("member"); if (member == null) { //重定向到登录页面 resp.sendRedirect(req.getContextPath() + "/views/member/login.jsp"); return; } int id = DataUtils.parseInt(member.getId().toString(), 0); //根据用户id查询对应的订单 List<Order> orders = orderService.queryOrderByMemberId(id); //将订单数据返回显示 req.setAttribute("orders", orders); //请求转发到order.jsp显示 req.getRequestDispatcher("/views/order/order.jsp").forward(req, resp); } /** * 显示订单项orderItem * * @param req * @param resp * @throws ServletException * @throws IOException */ protected void showOrderItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取当前orderid String orderId = req.getParameter("orderId"); //根据orderId返回对应的订单项orderItem List<OrderItem> orderItems = orderService.queryOrderItemByOrderId(orderId); //计算该order中所有orderItem的总商品数量和总价格 Integer totalCount = 0; BigDecimal totalPrice = BigDecimal.valueOf(0); for (OrderItem orderItem : orderItems) { totalCount += orderItem.getCount(); totalPrice = totalPrice.add(orderItem.getTotalPrice()); } System.out.println("totalCount=>" + totalCount); System.out.println("totalPrice=>" + totalPrice); //将订单项数据返回显示 //订单id req.setAttribute("orderId", orderId); //订单商品总数 req.setAttribute("totalCount", totalCount); //订单商品总额 req.setAttribute("totalPrice", totalPrice); //订单项 req.setAttribute("orderItems", orderItems); //请求转发到order_detail.jsp req.getRequestDispatcher("/views/order/order_detail.jsp").forward(req, resp); }
25.3.4前端页面修改
略
25.4完成测试
用户只有在登录情况下但能进入订单管理

点击详情的眼睛图案,即可查看该订单详情

26.功能24-过滤器权限验证
26.1需求分析/图解
- 加入过滤器权限验证,如果没有登录,查看购物车和添加到购物车时,页面将自动转到登录页面
- 除了购物车,网页还有很多这样的操作,都需要先登录才能使用。
- 比如,查看购物车页面,访问管理员manage目录下的jsp,还有Servlet等都需要先登录后才能访问。
26.2思路分析

26.3代码实现
web.xml中配置过滤器
<filter> <filter-name>AuthFilter</filter-name> <filter-class>com.li.furns.filter.AuthFilter</filter-class> <init-param> <!--这里配置之后,还需要在过滤器中编写规则放行--> <param-name>excludedUrls</param-name> <param-value>/views/manage/manage_login.jsp,/views/member/login.jsp</param-value> </init-param> </filter> <filter-mapping> <filter-name>AuthFilter</filter-name> <!--配置过滤器匹配url 1.在url-pattern中配置要拦截的url 2.需要拦截的url中也要分情况考虑, 比如/views/manage/下除了manage_login.jsp外都要拦截 对于这种在被拦截目录下但又需要放行的资源,我们可以在init-param中配置指定 --> <url-pattern>/views/cart/*</url-pattern> <url-pattern>/views/manage/*</url-pattern> <url-pattern>/views/member/*</url-pattern> <url-pattern>/views/order/*</url-pattern> <url-pattern>/cartServlet</url-pattern> <url-pattern>/manage/furnServlet</url-pattern> <url-pattern>/orderServlet</url-pattern> </filter-mapping>
AuthFilter
package com.li.furns.filter; import com.li.furns.entity.Member; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Arrays; import java.util.List; /** * 这是用于权限验证的过滤器,对指定的url进行验证 * 如果登录过,就放行;如果没有登录,就返回登录页面 * * @author 李 * @version 1.0 */ public class AuthFilter implements Filter { //后面我们把要排除的url放入到excludedUrls中 private List<String> excludedUrls; public void init(FilterConfig config) throws ServletException { //获取到配置的excludedUrls String strExcludedUrls = config.getInitParameter("excludedUrls"); //进行分割 String[] splitUrl = strExcludedUrls.split(","); //将splitUrl转成List,赋给excludedUrls excludedUrls = Arrays.asList(splitUrl); System.out.println("excludedUrls=>" + excludedUrls); } public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { //权限验证 HttpServletRequest req = (HttpServletRequest) request; //得到请求的url String url = req.getServletPath(); //判断是否要验证 if (!excludedUrls.contains(url)) {//如果url不在配置的规则中,就进行校验 //得到session中的member对象 Member member = (Member) req.getSession().getAttribute("member"); if (member == null) {//说明用户没有登录过 //转发到登录页面 //不要使用重定向,因为重定向的url符合过滤器规则时也会被拦截, //如果设置不合理就会出现 请求无线循环重定向的 情况 req.getRequestDispatcher("/views/member/login.jsp").forward(request, response); return;//返回 } } //否则就放行 chain.doFilter(request, response); } }
我们在用户登录时给用户的session中放了一个member对像,方便显示用户信息,同时也方便过滤器处理。因为之前我们是将管理员和用户分开的,因此管理员登录的处理在AdminServlet中。为了方便过滤,这里将admin的登录和member的登录都放到MemberServlet中进行,即不再将管理员和用户视为两张表。
MemberServlet.login()
/** * 处理会员和管理员的登录业务 * * @param request * @param response * @throws ServletException * @throws IOException */ public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.接收用户名和密码 //如果前端输入的是null,后台接收的数据为空串"" String username = request.getParameter("username"); String password = request.getParameter("password"); //2.调用MemberServiceImpl的login方法 Member member = memberService.login(new Member(null, username, password, null)); if (member == null) {//数据库中没有该用户,返回登录页面 //登录失败,将错误信息和登录会员名放入request域中 request.setAttribute("errInfo", "登录失败,用户名或者密码错误"); request.setAttribute("username", username); //注意路径 request.getRequestDispatcher("/views/member/login.jsp") .forward(request, response); } else {//登录成功 //创建session,将jsessionid作为cookie返回给浏览器 HttpSession session = request.getSession(); session.setMaxInactiveInterval(1800);//设置生命周期为30分钟 //将得到的member对象放入session域对象中 session.setAttribute("member", member); if ("admin".equals(member.getUsername())) { //跳转到登录成功页面 request.getRequestDispatcher("/views/manage/manage_menu.jsp") .forward(request, response); } else { //跳转到登录成功页面 request.getRequestDispatcher("/views/member/login_ok.jsp") .forward(request, response); } } }
26.4完成测试
-
在首页点击add to cart
因为该按钮实际上向cartServlet发出请求,因此被拦截,根据filter编写的逻辑请求转发到用户登录页面

2.在url地址栏直接访问管理员登录页面manage_login.jsp
该页面也处于被拦截的url中,但是当filter拦截后,发现该url在配置的excludedUrls中,根据编写的逻辑,会直接放行,因此可以访问到

管理员登录后,可以正常访问manage目录下的资源


【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!