家居网购项目(权限验证+事务管理)

发布于:2024-04-16 ⋅ 阅读:(193) ⋅ 点赞:(0)

文章目录

1.过滤器权限认证

1.程序框架图

image-20240211092524610

2.web.xml
    <filter>
        <filter-name>AdminAuthorization</filter-name>
        <filter-class>com.sxs.furns.filter.AdminAuthorization</filter-class>
        <init-param>
            <!--设置排除的uri-->
            <param-name>excludeUrls</param-name>
            <param-value>/jiaju_mail/views/manage/manage_login.jsp</param-value>
        </init-param>
    </filter>

    <!--除了登录的管理员页面都要进行管理员验证-->
    <filter-mapping>
        <filter-name>AdminAuthorization</filter-name>
        <url-pattern>/views/manage/*</url-pattern>
    </filter-mapping>
    <!--家居管理-->
    <filter-mapping>
        <filter-name>AdminAuthorization</filter-name>
        <url-pattern>/manage/furnServlet/*</url-pattern>
    </filter-mapping>


    <filter>
        <filter-name>MemberAuthorization</filter-name>
        <filter-class>com.sxs.furns.filter.MemberAuthorization</filter-class>
    </filter>

    <!--登录成功的界面,需要普通权限验证-->
    <filter-mapping>
        <filter-name>MemberAuthorization</filter-name>
        <url-pattern>/views/member/login_ok.jsp</url-pattern>
    </filter-mapping>
    <!--所有的购物车界面,需要普通权限验证-->
    <filter-mapping>
        <filter-name>MemberAuthorization</filter-name>
        <url-pattern>/views/cart/*</url-pattern>
    </filter-mapping>
    <!--购物车和订单servlet,需要普通权限验证-->
    <filter-mapping>
        <filter-name>MemberAuthorization</filter-name>
        <url-pattern>/orderServlet/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>MemberAuthorization</filter-name>
        <url-pattern>/cartServlet/*</url-pattern>
    </filter-mapping>
3.编写AdminAuthorization
package com.sxs.furns.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class AdminAuthorization implements Filter {
    private List<String> excludeUrlsList = new ArrayList<>(); //排除的资源
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //读取配置文件中的信息
        String excludeUrls = filterConfig.getInitParameter("excludeUrls");
        //按照,分割,并添加到集合中
        String[] split = excludeUrls.split(",");
        for (String s : split) {
            excludeUrlsList.add(s);
        }
        //放到servletContext中
        ServletContext servletContext = filterConfig.getServletContext();
        servletContext.setAttribute("excludeUrls", excludeUrlsList);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //查看session中的admin是否为true
        HttpSession session = ((HttpServletRequest) servletRequest).getSession();
        Object admin = session.getAttribute("admin");
        //获取uri
        String requestURI = ((HttpServletRequest) servletRequest).getRequestURI();
        //获取排除的uri
        List<String> excludeUrls = (List<String>) servletRequest.getServletContext().getAttribute("excludeUrls");
        //遍历并匹配
        for (String excludeUrl : excludeUrls) {
            System.out.println(excludeUrl);
            //如果匹配直接放行
            if (excludeUrl.equals(requestURI)) {
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
        }
        if (admin != null) {
            //放行
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            //重定向到管理员登录界面
            ((HttpServletResponse) servletResponse).sendRedirect("/jiaju_mail/views/manage/manage_login.jsp");
        }
    }

    @Override
    public void destroy() {

    }
}

4.编写MemberAuthorization
package com.sxs.furns.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * 普通权限认证
 * @author 孙显圣
 * @version 1.0
 */
public class MemberAuthorization implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpSession session = ((HttpServletRequest) servletRequest).getSession();
        //进行普通权限认证
        Object username = session.getAttribute("username");
        Object admin = session.getAttribute("admin");
        if (username != null || admin != null) {
            System.out.println("普通权限验证成功!");
            //放行
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            //重定向到用户登录界面
            ((HttpServletResponse) servletResponse).sendRedirect("/jiaju_mail/views/member/login.jsp");
        }
    }

    @Override
    public void destroy() {

    }
}

5.细节

如果想要过滤一个文件夹下除了某个资源的其余资源,可以将排除的资源URI其放在init-param中,然后通过filter的init方法将其放到servletContext中,然后在doFilter中直接放行

6.结果展示
1.未登录可以任意浏览商品

image-20240211114953238

2.点击添加购物车提示登录

image-20240211115035714

image-20240211115041741

3.点击后台管理,提示管理员登录

image-20240211115128144

image-20240211115115218

4.也做了其余资源的访问验证

2.事务管理

1.思路分析

image-20240211142121222

image-20240211142140091

2.重写JDBCUtilsByDruid
1.getConnection()方法
    private static ThreadLocal<Connection> threadLocalConn = new ThreadLocal<>(); //用于存放本线程的连接

    //重写getConnection方法,使其每个线程获取的是同一个连接
    public static Connection getConnection() {
        try {
            Connection connection = threadLocalConn.get(); //从threadlocal中获取当前线程的连接
            //如果没有获取到,则放入一个连接
            if (connection == null) {
                connection = dataSource.getConnection();
                connection.setAutoCommit(false); //取消自动提交
                threadLocalConn.set(connection);
            }
            return connection;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
2.commit()方法
    //提交事务
    public static void commit() {
        //获取连接
        Connection connection = threadLocalConn.get();
        //如果连接有效则提交事务并关闭连接
        if (connection != null) {
            try {
                connection.commit();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            } finally {
                try {
                    connection.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        //清除threadlocal的连接
        threadLocalConn.remove();
    }
3.rollback()方法
    //回滚事务
    public static void rollback() {
        Connection connection = threadLocalConn.get();
        if (connection != null) {
            try {
                connection.rollback();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            } finally {
                try {
                    connection.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        threadLocalConn.remove();
    }
4.删除BasicDao中的所有关闭数据库连接的语句

原因:数据库连接的关闭,交给最后提交事务或者回滚事务的时候再执行

image-20240211152822089

5.编写过滤器TransactionFilter
package com.sxs.furns.filter;

import com.sxs.furns.utils.JDBCUtilsByDruid;

import javax.servlet.*;
import java.io.IOException;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class TransactionFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain){
        //首先放行
        try {
            filterChain.doFilter(servletRequest, servletResponse);
            JDBCUtilsByDruid.commit();
        } catch (Exception e) {
            //如果在这次线程中有异常发生,则回滚
            System.out.println("发现异常,事务回滚!");
            JDBCUtilsByDruid.rollback();
        }

    }

    @Override
    public void destroy() {

    }
}

6.配置web.xml
    <!--在权限验证之后再编写事务过滤器-->
    <filter>
        <filter-name>TransactionFilter</filter-name>
        <filter-class>com.sxs.furns.filter.TransactionFilter</filter-class>
    </filter>
    <!--对所有请求进行过滤-->
    <filter-mapping>
        <filter-name>TransactionFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
7.查看调用可能出现问题的方法是不是抛出了异常

所有的servlet都是basicservlet反射调用的,并且都抛出了异常,这个异常最后会经过过滤器,所以可以在过滤器中捕获到异常

image-20240211153711602

3.结果展示
1.将OrderDaoImpl中的sql故意写错

image-20240211154703922

2.执行保存订单操作

image-20240211165406002

image-20240211165420900

image-20240211165433434

3.查看数据库信息(回滚了,没有生成记录)

image-20240211165458599

image-20240211165508047

3.统一错误页面

1.需求分析

image-20240211170301996

2.修改web.xml
    <!--配置错误页面-->
    <error-page>
        <error-code>404</error-code>
        <location>/views/error/404.jsp</location>
    </error-page>
    <error-page>
        <error-code>500</error-code>
        <location>/views/error/500.jsp</location>
    </error-page>
3.导入两个页面

image-20240211171312340

4.修改TransactionFilter,将异常抛给tomcat

image-20240211171629237

5.结果展示

image-20240211171404475

image-20240211171743485

4.会员订单管理—分页查询

需求分析

可以返回已登录的会员的历史订单信息

1.编写dao层
1.修改OrderDao
    //3.获取当前页需要展示的数据
    public List<Order> getPageItems(int begin, int pageSize, String id);
    //4.获取一共的记录条数
    public Integer getTotalRow(String id);
2.修改OrderDaoImpl
    /**
     * 分页查询订单
     * @param begin
     * @param pageSize
     * @return
     */
    @Override
    public List<Order> getPageItems(int begin, int pageSize, String id) {

        String sql = "select id, create_time as createTime, price, status, member_id as memberId from `order` where id like ? limit ?, ?";
        return queryMulti(sql, Order.class, "%-" + id , begin, pageSize);
    }

    /**
     * 获取总记录条数
     * @return
     */
    @Override
    public Integer getTotalRow(String id) {
        String sql = "select count(*) from `order` where id like ?";
        return ((Number) queryScalar(sql,"%-" + id)).intValue();
    }
3.单元测试
    @Test
    public void getPageItems() {
        //查询id为1的会员的订单信息
        List<Order> pageItems = orderDao.getPageItems(0, 3, "1");
        for (Order pageItem : pageItems) {
            System.out.println(pageItem);
        }
    }

    @Test
    public void getTotalRow() {
        System.out.println("总的记录数为:" + orderDao.getTotalRow("1"));
    }

image-20240211193017269

image-20240211200733207

2.编写service层
1.修改OrderService
    //3.分页显示订单
    public Page<Order> getPageItems(int pageNo, int pageSize, String username);
2.修改OrderServiceImpl
    /**
     * 根据当前页号和分页的大小返回对应的page对象
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public Page<Order> getPageItems(int pageNo, int pageSize, String username) {
        //根据姓名获取用户id
        Member member = memberDao.queryMemberByUsername(username);
        //获取总记录数
        Integer totalRow = orderDao.getTotalRow(member.getId().toString());
        //计算总页数
        Integer pageTotalCount = totalRow / pageSize;
        if (totalRow % pageSize > 0) {
            pageTotalCount ++;
        }
        //计算begin
        int begin = (pageNo - 1) * pageSize;

        //获取当页的所有数据
        List<Order> pageItems = orderDao.getPageItems(begin, pageSize, member.getId().toString());
        //填充page
        Page<Order> orderPage = new Page<>();
        orderPage.setPageNo(pageNo);
        orderPage.setPageSize(pageSize);
        orderPage.setPageTotalCount(pageTotalCount);
        orderPage.setTotalRow(totalRow);
        orderPage.setItems(pageItems);
        return orderPage;
    }
3.单元测试
    OrderService orderService = new OrderServiceImpl();
    @Test
    public void getPageItems() {
        Page<Order> pageItems = orderService.getPageItems(1, 3, "admin");
        System.out.println(pageItems);
    }

image-20240211194809877

3.编写web层
1.修改OrderServlet
    //分页显示订单
    public void showPageItems(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取数据
        Integer pageNo = DataUtils.parseInt(req.getParameter("pageNo"), 1); //默认第一页
        Integer pageSize = DataUtils.parseInt(req.getParameter("pageSize"), 6); //默认六条记录
        String username = req.getParameter("username");
        //获取page对象
        Page<Order> page = orderService.getPageItems(pageNo, pageSize, username);
        //请求转发
        req.setAttribute("page", page);
        req.getRequestDispatcher("/views/order_manage/order_manage.jsp").forward(req, resp);
    }
2.修改order_manage.jsp
1.显示信息

image-20240211201128675

2.分页导航条

image-20240211201147642

4.结果演示
1.会员登录

image-20240211202317112

2.会员点击订单管理只会显示当前会员的历史订单

image-20240211202415806

5.管理员订单管理—分页查询

需求分析

管理员的订单管理,显示的是所有会员的订单

1.编写dao层
1.修改OrderDao
    //5.管理员获取总体的记录条数
    public Integer getTotalRow();
    //6.管理员获取当前页需要展示的数据
    public List<Order> getPageItems(int begin, int pageSize);
2.修改OrderDaoImpl
    @Override
    public Integer getTotalRow() {
        String sql = "select count(*) from `order`";
        return ((Number) queryScalar(sql)).intValue();
    }

    @Override
    public List<Order> getPageItems(int begin, int pageSize) {
        String sql = "select id, create_time as createTime, price, status, member_id as memberId from `order` limit ?, ?";
        return queryMulti(sql, Order.class, begin, pageSize);
    }
2.编写service层
1.修改OrderService
    //4.管理员分页显示订单
    public Page<Order> getPageItems(int pageNo, int pageSize);
2.修改OrderServiceImpl
    @Override
    public Page<Order> getPageItems(int pageNo, int pageSize) {

        //获取总记录数
        Integer totalRow = orderDao.getTotalRow();
        //计算总页数
        Integer pageTotalCount = totalRow / pageSize;
        if (totalRow % pageSize > 0) {
            pageTotalCount ++;
        }
        //计算begin
        int begin = (pageNo - 1) * pageSize;

        //获取当页的所有数据
        List<Order> pageItems = orderDao.getPageItems(begin, pageSize);
        //填充page
        Page<Order> orderPage = new Page<>();
        orderPage.setPageNo(pageNo);
        orderPage.setPageSize(pageSize);
        orderPage.setPageTotalCount(pageTotalCount);
        orderPage.setTotalRow(totalRow);
        orderPage.setItems(pageItems);
        return orderPage;
    }
3.编写web层
1.修改OrderServlet
    //管理员分页显示订单
    public void showAllPageItems(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取数据
        Integer pageNo = DataUtils.parseInt(req.getParameter("pageNo"), 1); //默认第一页
        Integer pageSize = DataUtils.parseInt(req.getParameter("pageSize"), 6); //默认六条记录
        //获取page对象
        Page<Order> page = orderService.getPageItems(pageNo, pageSize);
        //请求转发
        req.setAttribute("page", page);
        req.getRequestDispatcher("/views/manage/order_manage.jsp").forward(req, resp);
    }
2.修改order_manage.jsp
1.显示信息

image-20240211211148413

2.分页导航条

image-20240211211203728

4.结果展示

image-20240211211304583


网站公告

今日签到

点亮在社区的每一天
去签到