一、前台功能

1、首页处理流程

首页处理流程

2、首页显示轮播图

1、定义BannerHomepageVO

/**
 * @document: 轮播图视图对象 用于和前端页面(index.html)进行交互
 * @Author:SmallG
 * @CreateTime:2023/9/11+9:08
 */

public class BannerHomepageVO {
    private Long id;
    private String image;
    
    省略...
}

2、在BannerService中添加方法:

/**
 * 前端页面查询所有轮播图
 *
 * @return
 */
List<BannerHomepageVO> findAllHomepage();

3、在BannerServiceImpl中实现方法:

@Override
public List<BannerHomepageVO> findAllHomepage() {
    //获取所有的轮播图对象
    List<Banner> banners = bannerMapper.selectAll();
    //对象转换
    List<BannerHomepageVO> bannerHomepageVOS = banners.stream()
            .map(banner -> new BannerHomepageVO(
                    banner.getId(),
                    banner.getImage()
            )).collect(Collectors.toList());
    return bannerHomepageVOS;
}

4、添加首页控制器HomepageController :

@GetMapping("/home/banners")
@ResponseStatus(HttpStatus.OK) //200查询成功
public List<BannerHomepageVO> findBanners() {
    logger.info("控制层查询所有轮播图");
    List<BannerHomepageVO> bannerHomepageVOS = bannerService.findAllHomepage();
    return bannerHomepageVOS;
}

3、首页显示商品

重构显示分类功能

为了统一处理首页显示的数据,方便在后期统一处理访问权限,将显示分类后端功能,调整到HomepageController中,具体步骤如下:

1、在HomepageController中注入CategoryService,然后添加控制器方法,获取全部的分类:

@Autowired
private CategoryService categoryService;

/**
 * 前台首页所有商品类别
 *
 * @return
 */
@GetMapping("/categories")
@ResponseStatus(HttpStatus.OK) //状态码200
public List<CategoryVO> findCategories() {
    logger.info("控制器查询首页商品类别");
    List<CategoryVO> categoryVOS = categoryService.findHomepageCategories();
    return categoryVOS;
}

2、更新index.html 中获取分类的方法:

//获取分类
getCategories() {
  axios.get('/home/categories').then(res => {
    this.categories = res.data
    //设置默认选定的分类ID
    this.selectedCategoryId = this.categories[0].id
    //this.getProductsByCategoryId()
  })
}

二、会话状态和过滤器

1、Cookies

使用Cookies技术可以解决在Web应用中记录用户会话状态的问题。在HTTP协议中,每个请求和响应都是独立的,服务器无法保存任何关于之前的请求或响应的信息,因此需要Cookies技术来维护会话状态。

用户登录后,会给客户端发送一个cookie,服务器通过识别cookie对用户进行识别。

cookie创建完成之后,默认是临时的,当浏览器关闭以后就失效。

下发Cookies

/**
 * @document: 用于向客户端发送cookie
 * 1、cookie中的信息是明码保存,一些敏感信息不能写在cookie
 * 2、单个cookie的大小不能超过4k
 * 3、单个站点最多只能写20个Cookie
 * 4、按照规定:只能读取自己站点的Cookie
 */

@RestController
public class CookieController {
    private static final Logger logger = LoggerFactory.getLogger(CookieController.class);

    /**
     * 服务器向客户端发cookie
     */
    @GetMapping("/setCookies")
    public String setCookies(HttpServletResponse response) {
        logger.info("服务器向客户端发送cookie");
        //1、创建cookie,一个cookie只能写一个数据
        Cookie cookie = new Cookie("username", "SmallG");
        //2、设置cookie
        //设置cookie的有效期
        cookie.setMaxAge(7 * 24 * 3600); //保存10秒钟
        //3、发送cookie
        response.addCookie(cookie);
        return "服务器向客户端发送cookie";
    }

    /**
     * 服务器获取客户端的cookie
     */
    @GetMapping("/getCookies")
    public String getCookies(HttpServletRequest request) {
        //1、获取服务器向客户端写的所有Cookie,返回一个数组
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            //获取cookie的名字
            String name = cookie.getName();
            //获取cookie保存的数据
            String value = cookie.getValue();
            logger.info("name:{},value:{}", name, value);
        }
        return "服务器端获取客户端的cookie";
    }

    //读cookie的简单方法
    @GetMapping("/getCookies2")
    public String getCookies2(@CookieValue String username) {
        logger.info("username:{}", username);
        return "服务器端获取客户端的cookie2";
    }
}

2、Session

Session可以保存敏感信息,一旦建立的session,不同浏览器的请求会显示两个客户端

HttpSession API

管理会话,在多个页面共享数据,比如访问淘宝网,在一个页面登录后其他的就不用登录了。

以下是HttpSession API中的一些常用方法:

  • setAttribute(String name, Object value): 将一个对象绑定到当前会话中的指定属性名,可以通过getAttribute()方法来获取这个对象。
  • getAttribute(String name): 获取与指定属性名关联的对象,如果没有找到则返回null。
  • getId(): 获取会话的唯一标识符,也就是Session ID。
  • setMaxInactiveInterval(int interval): 设置会话的最大不活动时间间隔,以秒为单位。如果在这段时间内没有活动,则会话将被销毁,默认有效期是30分钟。
  • invalidate(): 使会话失效,即清除会话中存储的所有数据。比如清除登录信息时候使用。
/**
 * @document: Session控制器
 * @Author:SmallG
 * @CreateTime:2023/9/11+15:13
 */

@RestController
public class SessionController {
    private static final Logger logger = LoggerFactory.getLogger(SessionController.class);


    /**
     * 设置session
     */
    @GetMapping("/setSession")
    public String setSession(HttpServletRequest request) {
        logger.info("设置session");
        //获取session
        HttpSession session = request.getSession();
        //往Session中存入数据
        session.setAttribute("username", "zhangsan");
        //获取session标识
        String sessionId = session.getId();
        //获取有效期 单位默认是秒 不推荐设置其他时间
        int maxInactiveInterval = session.getMaxInactiveInterval();
        logger.info("session默认有效期:{}", maxInactiveInterval);
        return "设置session,sessionId:" + sessionId;
    }

    /**
     * 读取session
     */
    @GetMapping("/getSession")
    public String getSession(HttpSession session) { //获取session的简单方法 直接作为方法的参数
        logger.info("读取session");
        String sessionId = session.getId();
        //获取session中的数据
        String username = (String) session.getAttribute("username"); //转换成字符串需要强转
        logger.info("username:{}", username);
        return "读取session,sessionId=" + sessionId + ",username=" + username;
    }

    /**
     * 清空session
     */
    @GetMapping("/clearSession")
    public String clearSession(HttpSession session){
        logger.info("清空session");
        //让session强制过期
        session.invalidate(); //常用于退出登录
        return "清空session";
    }
}

3、过滤器

不登录不能访问,用于在请求到达 Web 应用程序的目标资源之前,对请求进行预处理和后处理。

下面是过滤器的一些API及其作用:

1、Filter接口:所有过滤器都必须实现该接口。Filter接口定义了三个方法:

  • init()方法:初始化过滤器,在容器启动时执行,仅执行一次;
  • doFilter()方法:处理请求和响应,执行过滤器的核心逻辑;
  • destroy()方法:销毁过滤器,在容器关闭时执行,仅执行一次。

2、FilterChain接口:用于传递请求和响应给过滤器链中的下一个过滤器或Servlet。FilterChain接口定义了一个方法:

  • doFilter(ServletRequest request, ServletResponse response):传递请求和响应给下一个过滤器或Servlet。

3、urlPatterns 是 javax.servlet.annotation.WebFilter 注解中的一个参数,用于指定需要过滤的请求路径。可以使用一些通配符规则来匹配 URL。

  • /*:匹配所有 URL,不包括子路径
  • /path/*:匹配以 /path/ 开头的所有 URL,包括子路径
  • /path:匹配精确的路径,不包括子路径
/**
 * @document: 创建一个过滤器
 * 1、实现接口 Filter
 * 2、实现接口的方法
 * 3、处理过滤逻辑
 * 4、对过滤器进行配置
 * @Author:SmallG
 * @CreateTime:2023/9/11+16:33
 */
@WebFilter(urlPatterns = {"/*","/path/*"}) //声明过滤器,拦截所有请求
public class MyFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(MyFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        logger.info("过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //获取HttpServletRequest对象
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        //获取请求路径
        String uri = request.getRequestURI();
        logger.info("请求路径:{}", uri);
        //放行
        filterChain.doFilter(servletRequest, servletResponse);
        logger.info("离开服务器");
    }

    @Override
    public void destroy() {
        logger.info("过滤器被销毁");
    }
}

在启动类里面添加注解:

@ServletComponentScan //扫描当前包和所有子包的所有带有@WebFilter注解的类

4、在项目中添加过滤器

//用户登录认证过滤器
//用户访问后台资源 拦截未登录的用户
//如果用户未登录 直接跳转到登录页面
//拦截admin.html 和 以/api/开头的所有请求
@WebFilter(filterName = "securityFilter", urlPatterns = {"/admin.html", "/api/*"})
public class SecurityFilter implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(SecurityFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        logger.info("用户请求认证");
        //获取HttpServletRequest对象
        HttpServletRequest request = (HttpServletRequest) servletRequest;

        //获取httpservletResponse对象用于对客户端目标重定向
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        //获取httpsession对象
        HttpSession session = request.getSession();
        //从HttpSession对象中获取登录的用户对象
        UserVO userVO = (UserVO) session.getAttribute("loginUser");
        //判断用户是否登录
        if (userVO == null) {
            //用户未登录 访问登录页面
            response.sendRedirect("/login.html"); //目标重定向
            logger.info("重定向到登录页面");
        } else {
            // 用户登录 放行
            filterChain.doFilter(servletRequest, servletResponse);
            logger.info("放行");
        }
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
最后修改:2023 年 09 月 11 日
如果觉得我的文章对你有用,请随意赞赏