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();
}
/**
* 增加广告点击次