如何使用Java编写CMS系统的站内广告模块

1. 概述

站内广告模块是CMS(Content Management System)系统中非常重要的一部分,它可以帮助网站管理员轻松地管理广告信息,并且可以实现预定广告、实时曝光、点击数统计等功能。本文将介绍如何使用Java编写CMS系统的站内广告模块。

2. 需求分析

2.1 前台需求

站内广告模块在前台需要提供以下功能:

展示广告信息。

记录广告的点击次数并计入广告主账户。

根据广告位、发布时间、过期时间等条件过滤广告信息。

提供多种广告展示模式,如轮播、固定、滚动等。

2.2 后台需求

站内广告模块在后台需要提供以下功能:

发布广告信息。

管理已发布的广告信息。

实现广告预定、付款、结算等业务功能。

根据广告位、发布时间、过期时间等条件过滤广告信息。

提供多种广告展示模式的设置。

3. 技术选型

在本文中,我们选择以下技术来实现站内广告模块:

Java作为编程语言。

MySQL作为数据库。

Spring作为框架。

FreeMarker作为模板引擎。

4. 技术实现

4.1 数据库设计

为了实现站内广告管理,我们需要设计以下数据库表:

CREATE TABLE `ad_position` (

`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '广告位ID',

`name` varchar(50) NOT NULL COMMENT '广告位名称',

`description` varchar(255) DEFAULT NULL COMMENT '广告位描述',

PRIMARY KEY (`id`)

);

CREATE TABLE `ad` (

`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '广告ID',

`position_id` int(11) NOT NULL COMMENT '广告位ID',

`title` varchar(50) NOT NULL COMMENT '广告标题',

`image_url` varchar(255) DEFAULT NULL COMMENT '广告图片路径',

`link_url` varchar(255) DEFAULT NULL COMMENT '广告跳转链接',

`start_time` datetime DEFAULT NULL COMMENT '广告开始展示时间',

`end_time` datetime DEFAULT NULL COMMENT '广告结束展示时间',

`add_time` datetime DEFAULT NULL COMMENT '广告添加时间',

`update_time` datetime DEFAULT NULL COMMENT '广告更新时间',

`click_count` int(11) DEFAULT '0' COMMENT '广告点击次数',

`status` tinyint(2) DEFAULT '0' COMMENT '广告状态:0-未开始展示 1-已经展示 2-已经结束展示',

PRIMARY KEY (`id`)

);

4.2 后台功能实现

在后台管理功能中,我们需要实现以下功能:

广告位管理:添加、编辑、删除广告位信息。

广告管理:添加、编辑、删除广告信息。

统计广告点击次数。

过期广告批量下架。

接下来,我们逐一实现以上功能。

4.2.1 广告位管理

广告位管理包含以下功能:

查询广告位列表。

添加广告位信息。

编辑广告位信息。

删除广告位信息。

在广告位实体类中,我们定义以下属性:

public class AdPosition {

/**

* 广告位ID

*/

private Integer id;

/**

* 广告位名称

*/

private String name;

/**

* 广告位描述

*/

private String description;

// getter和setter方法省略

}

广告位DAO层接口:

public interface AdPositionDao {

Integer insert(AdPosition adPosition);

Integer update(AdPosition adPosition);

Integer deleteById(Integer id);

AdPosition selectById(Integer id);

AdPosition selectByName(String name);

List<AdPosition> selectAll();

}

广告位DAO层的MySQL实现:

@Repository

public class AdPositionDaoImpl implements AdPositionDao {

@Autowired

private JdbcTemplate jdbcTemplate;

@Override

public Integer insert(AdPosition adPosition) {

String sql = "insert into ad_position(name, description) values (?, ?)";

return jdbcTemplate.update(sql, adPosition.getName(), adPosition.getDescription());

}

@Override

public Integer update(AdPosition adPosition) {

String sql = "update ad_position set name = ?, description = ? where id = ?";

return jdbcTemplate.update(sql, adPosition.getName(), adPosition.getDescription(), adPosition.getId());

}

@Override

public Integer deleteById(Integer id) {

String sql = "delete from ad_position where id = ?";

return jdbcTemplate.update(sql, id);

}

@Override

public AdPosition selectById(Integer id) {

String sql = "select id, name, description from ad_position where id = ?";

List<AdPosition> adPositions = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(AdPosition.class), id);

if (adPositions != null && adPositions.size() > 0) {

return adPositions.get(0);

}

return null;

}

@Override

public AdPosition selectByName(String name) {

String sql = "select id, name, description from ad_position where name = ?";

List<AdPosition> adPositions = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(AdPosition.class), name);

if (adPositions != null && adPositions.size() > 0) {

return adPositions.get(0);

}

return null;

}

@Override

public List<AdPosition> selectAll() {

String sql = "select id, name, description from ad_position";

List<AdPosition> adPositions = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(AdPosition.class));

return adPositions;

}

}

广告位管理的Service层:

@Service

public class AdPositionService {

@Autowired

private AdPositionDao adPositionDao;

public Integer save(AdPosition adPosition) {

if (adPosition.getId() == null) {

AdPosition position = adPositionDao.selectByName(adPosition.getName());

if (position != null) {

// 广告位名称不能重复

return -1;

}

return adPositionDao.insert(adPosition);

} else {

return adPositionDao.update(adPosition);

}

}

public Integer deleteById(Integer id) {

return adPositionDao.deleteById(id);

}

public AdPosition getById(Integer id) {

return adPositionDao.selectById(id);

}

public List<AdPosition> getAll() {

return adPositionDao.selectAll();

}

}

4.2.2 广告管理

广告管理包含以下功能:

查询广告列表。

添加广告信息。

编辑广告信息。

删除广告信息。

统计广告点击次数。

过期广告批量下架。

在广告实体类中,我们定义以下属性:

public class Ad {

/**

* 广告ID

*/

private Integer id;

/**

* 广告位ID

*/

private Integer positionId;

/**

* 广告标题

*/

private String title;

/**

* 广告图片路径

*/

private String imageUrl;

/**

* 广告跳转链接

*/

private String linkUrl;

/**

* 广告开始展示时间

*/

private Date startTime;

/**

* 广告结束展示时间

*/

private Date endTime;

/**

* 广告添加时间

*/

private Date addTime;

/**

* 广告更新时间

*/

private Date updateTime;

/**

* 广告点击次数

*/

private Integer clickCount;

/**

* 广告状态:0-未开始展示 1-已经展示 2-已经结束展示

*/

private Integer status;

// getter和setter方法省略

}

广告DAO层接口:

public interface AdDao {

Integer insert(Ad ad);

Integer update(Ad ad);

Integer deleteById(Integer id);

Ad selectById(Integer id);

List<Ad> selectAll();

/**

* 分页查询广告列表

*

* @param page 当前页码

* @param pageSize 每页记录数

* @param ad 查询条件

* @return 广告列表

*/

List<Ad> selectByPage(Integer page, Integer pageSize, Ad ad);

/**

* 查询广告列表总记录数

*

* @param ad 查询条件

* @return 广告列表总记录数

*/

Integer selectCount(Ad ad);

/**

* 批量下架过期广告

*/

void offlineExpiredAd();

/**

* 增加广告点击次数

*

* @param ad 广告信息

* @return 更新记录数

*/

Integer increaseClickCount(Ad ad);

}

广告DAO层的MySQL实现:

@Repository

public class AdDaoImpl implements AdDao {

@Autowired

private JdbcTemplate jdbcTemplate;

@Override

public Integer insert(Ad ad) {

String sql = "insert into ad(position_id, title, image_url, link_url, start_time, end_time, click_count, status) " +

"values (?, ?, ?, ?, ?, ?, ?, ?)";

return jdbcTemplate.update(sql, ad.getPositionId(), ad.getTitle(), ad.getImageUrl(), ad.getLinkUrl(),

ad.getStartTime(), ad.getEndTime(), ad.getClickCount(), ad.getStatus());

}

@Override

public Integer update(Ad ad) {

String sql = "update ad set position_id = ?, title = ?, image_url = ?, link_url = ?, start_time = ?, " +

"end_time = ?, click_count = ?, status = ? where id = ?";

return jdbcTemplate.update(sql, ad.getPositionId(), ad.getTitle(), ad.getImageUrl(), ad.getLinkUrl(),

ad.getStartTime(), ad.getEndTime(), ad.getClickCount(), ad.getStatus(), ad.getId());

}

@Override

public Integer deleteById(Integer id) {

String sql = "delete from ad where id = ?";

return jdbcTemplate.update(sql, id);

}

@Override

public Ad selectById(Integer id) {

String sql = "select id, position_id, title, image_url, link_url, start_time, end_time, add_time, update_time, " +

"click_count, status from ad where id = ?";

List<Ad> ads = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Ad.class), id);

if (ads != null && ads.size() > 0) {

return ads.get(0);

}

return null;

}

@Override

public List<Ad> selectAll() {

String sql = "select id, position_id, title, image_url, link_url, start_time, end_time, add_time, update_time, " +

"click_count, status from ad";

List<Ad> ads = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Ad.class));

return ads;

}

@Override

public List<Ad> selectByPage(Integer page, Integer pageSize, Ad ad) {

StringBuilder sb = new StringBuilder();

sb.append("select id, position_id, title, image_url, link_url, start_time, end_time, add_time, update_time, ");

sb.append("click_count, status from ad where 1 = 1");

List<Object> params = new ArrayList<>();

if (ad.getPositionId() != null) {

sb.append(" and position_id = ?");

params.add(ad.getPositionId());

}

if (ad.getStatus() != null) {

sb.append(" and status = ?");

params.add(ad.getStatus());

}

if (StringUtils.isNotBlank(ad.getTitle())) {

sb.append(" and title like ?");

params.add("%" + ad.getTitle() + "%");

}

Integer startIndex = (page - 1) * pageSize;

sb.append(" order by id desc limit ?, ? ");

params.add(startIndex);

params.add(pageSize);

return jdbcTemplate.query(sb.toString(), new BeanPropertyRowMapper<>(Ad.class), params.toArray());

}

@Override

public Integer selectCount(Ad ad) {

StringBuilder sb = new StringBuilder();

sb.append("select count(*) from ad where 1 = 1");

List<Object> params = new ArrayList<>();

if (ad.getPositionId() != null) {

sb.append(" and position_id = ?");

params.add(ad.getPositionId());

}

if (ad.getStatus() != null) {

sb.append(" and status = ?");

params.add(ad.getStatus());

}

if (StringUtils.isNotBlank(ad.getTitle())) {

sb.append(" and title like ?");

params.add("%" + ad.getTitle() + "%");

}

return jdbcTemplate.queryForObject(sb.toString(), Integer.class, params.toArray());

}

@Override

public void offlineExpiredAd() {

String sql = "update ad set status = 2 where status = 1 and end_time < now()";

jdbcTemplate.update(sql);

}

@Override

public Integer increaseClickCount(Ad ad) {

String sql = "update ad set click_count = click_count + 1 where id = ?";

return jdbcTemplate.update(sql, ad.getId());

}

}

广告管理的Service层:

@Service

public class AdService {

@Autowired

private AdDao adDao;

// ...

/**

* 分页查询广告列表

*

* @param page 当前页码

* @param pageSize 每页记录数

* @param positionId 广告位ID

* @param status 广告状态

* @param title 广告标题(模糊匹配)

* @return 广告列表

*/

public List<Ad> getByPage(Integer page, Integer pageSize, Integer positionId, Integer status, String title) {

Ad ad = new Ad();

ad.setPositionId(positionId);

ad.setStatus(status);

ad.setTitle(title);

return adDao.selectByPage(page, pageSize, ad);

}

/**

* 查询广告列表总记录数

*

* @param positionId 广告位ID

* @param status 广告状态

* @param title 广告标题(模糊匹配)

* @return 广告列表总记录数

*/

public Integer getCount(Integer positionId, Integer status, String title) {

Ad ad = new Ad();

ad.setPositionId(positionId);

ad.setStatus(status);

ad.setTitle(title);

return adDao.selectCount(ad);

}

/**

* 批量下架过期广告

*/

public void offlineExpiredAd() {

adDao.offlineExpiredAd();

}

/**

* 增加广告点击次