概述

开发背景

校园新闻平台是以新闻宣传机构的在线信息发布需求为基础,随着数字化和信息化的快速发展,校园新闻在校园内的传播和沟通中变得越来越重要。学校需要一个有效的管理系统来整合、发布和传播校园新闻,以满足师生、校友和其他利益相关者的信息需求。借助互联网技术开发的信息化平台。在这一平台之上,不仅可以看到与常规纸质报纸相同的信息,还有助于实现新闻信息的规范化管理,为读者和采编人员查询和阅读带来便利。从目前看,通过网络获取新闻信息的人群远远大于纸质媒介用户,而且两者之间的差距还在进一步扩大。
在学校网站上,校园新闻平台是最为重要的组成部分,其主要作用有两个:一.是动态发布校内新闻或者重大项目公示;二是向社会传递学校的办学思路、教学成果、科研进展等,使学校获得更高的知名度和社会认可度。因此,研究网络环境下的电子新闻媒体,开发校园新闻平台完备校园网的重要工作之一。首先对校园新闻平台工作的实际需求进行了分析,特别是对其业务需求做了详尽的分析;而后,对校园新闻平台做了总体设计,从系统结构、总体框架、数据库等方面进行了详细阐述。在数据库设计上,阐述了该系统的概念结构设计、逻辑结构设计,描述了主要库表。从功能需求结构来看,校园新闻平台主要包括新闻浏览,论坛讨论和新闻管理三大功能模块。总之,开发一个校园新闻管理系统可以满足学校信息传播的需求,提高信息发布效率,增强用户参与度和体验,促进校园文化交流,并提供数据支持进行进一步的分析和优化。这样的系统将为学校带来更好的信息管理和校园文化建设。

开发目标

对于用户

  • 用户可以浏览全部新闻
  • 用户可以按照不同类型进行查阅新闻
  • 用户可以登录/注册论坛
  • 用户可以在不同的板块下发帖
  • 用户可以在帖子后面追加评论
  • 用户可以修改自己的密码

对于管理员

  • 管理员可以对用户进行维护
  • 管理员可以删除不友好的帖子或评论
  • 管理员可以按照关键字来查询帖子或新闻
  • 写手可以发表新闻
  • 审核员可以审核自身以下等级的新闻并可以发表新闻
  • 总管理可以审核所有等级的新闻,可以发布新闻,管理用户,维护管理员,管理论坛,管理新闻

设计原则

  1. 单一职责原则(Single Responsibility Principle,SRP):一个类或模块应该只有一个责任。这样可以降低类的复杂性,提高代码的可读性和可维护性。
  2. 开放封闭原则(Open-Closed Principle,OCP):软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。通过使用抽象和接口,可以在不修改现有代码的情况下扩展系统功能。
  3. 里氏替换原则(Liskov Substitution Principle,LSP):子类型必须能够替换它们的父类型。这意味着子类应该与其父类具有相同的行为,并且可以无缝地替换父类的实例。
  4. 依赖倒置原则(Dependency Inversion Principle,DIP):高层模块不应该依赖于低层模块,它们应该依赖于抽象。通过引入抽象接口,可以降低模块之间的耦合度,提高系统的灵活性和可测试性。
  5. 接口隔离原则(Interface Segregation Principle,ISP):客户端不应该依赖它们不需要的接口。接口应该细化,以满足特定客户端的需求,避免接口过于臃肿和冗余。
  6. 迪米特法则(Law of Demeter,LoD):一个对象应该对其他对象有尽可能少的了解。模块之间应该通过最小的接口进行通信,降低耦合度。
  7. 高内聚低耦合原则:模块内的组件应该紧密相关,而不同模块之间的依赖应该尽量减少。这样可以提高代码的可维护性和可测试性。
  8. 面向对象设计原则:封装、继承和多态是面向对象设计的基本原则。合理应用这些原则可以提高代码的可重用性和灵活性。

数据库设计

1.用户表(user)

字段 类型 说明
id varchar 用户编号
password varchar 用户密码

2.管理员表(admin)

字段 类类型 说明
id varchar 管理员编号
password varchar 管理员密码
level int 管理员等级

注:管理员有四个身份:总管理,一级审核,二级审核,写手。每个身份登录可以看到不同的界面,在数据库的level中分别用1,2,3,4标识

3.学校新闻表(schoolnews)

字段 类型 说明
id int 新闻编号
writer varchar 写手编号
title varchar 新闻标题
word varchar 新闻内容
time datetime 创建时间
type varchar 新闻类型
emo int 审核人编号
wlevel int 写手等级

4.论坛表(news)

字段 类型 说明
id int 编号
user varchar 发表人
title varchar 题目
news varchar 正文
type varchar 类型
time datetime 发表时间

5.评论表(log)

字段 类型 说明
id int 评论编号
lzid int 论坛问题编号
loguser varchar 评论者编号
title varchar 评论标题
log varchar 评论内容
time datetime 评论时间

项目开发

开发环境

开发工具:

  • IntelliJ IDEA 2022.3.3
  • apache-maven-3.6.3
  • apache-tomcat-9.0.69
  • jdk1.8
  • Lombok

技术栈:

  • Springboot
  • Spring-MVC
  • myBatis-Puls
  • thymeleaf

新建项目

1.新建项目

image-20230606095539889

2.添加依赖

image-20230606095718685

环境配置

1.配置application.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#关闭模版引擎缓存
spring:
thymeleaf:
cache: false
#配置文件的位置
messages:
basename: i18n.login
#以下为数据库mybatis配置
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/hello?useUnicode=true&characterEncoding=utf-8
# 如果时区异常可以加入&severTimezone=UTC
driver-class-name: com.mysql.jdbc.Driver
mvc:
format:
date: yyyy-MM-dd
#mybatis配置
mybatis:
type-aliases-package: com.asuka.hellospring.pojo
mapper-locations: classpath:mybatis/mapper/*.xml

2.给pom.xml添加依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
		<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>

<!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>

<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.3</version>
</dependency>
<!-- 热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 这个需要为 true 热部署才有效 -->
</dependency>

开发过程

新闻部份

1.创建实体(Schoolnews)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Schoolnews {
int id;
String writer;
String title;
String word;

String type;
int emo;
int wlevel;

@TableField(fill= FieldFill.INSERT)
Date time;
}

2.配置mapper

1
2
3
@Mapper
public interface SchoolnewsMapper extends BaseMapper<Schoolnews> {
}

3.配置控制器

根据标签选择新闻(回显全部新闻)

——SnewsController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
@RequestMapping("/snews")
public String newjud(Model model, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum, @RequestParam(defaultValue = "7", value = "pageSize") Integer pageSize) {

//实现倒序输出(校内新闻)
QueryWrapper<Schoolnews> newsQueryWrapper = new QueryWrapper<>();
newsQueryWrapper.orderByDesc("id");//倒序
newsQueryWrapper.eq("emo", 3);
newsQueryWrapper.eq("type", "校内新闻");

PageHelper.startPage(pageNum, pageSize);
List<Schoolnews> schoolnews = schoolnewsMapper.selectList(newsQueryWrapper);
model.addAttribute("sdutcmnews", schoolnews);


//实现倒序输出(院系速递)
QueryWrapper<Schoolnews> wrapperb = new QueryWrapper<>();
wrapperb.orderByDesc("id");
wrapperb.eq("emo", 3);
wrapperb.eq("type", "院系速递");
PageHelper.startPage(pageNum, pageSize);
List<Schoolnews> schoolnewsb = schoolnewsMapper.selectList(wrapperb);
model.addAttribute("yuanxinews", schoolnewsb);


//实现倒序输出(通知公告)
QueryWrapper<Schoolnews> wrapperc = new QueryWrapper<>();
wrapperc.orderByDesc("id");
wrapperc.eq("emo", 3);
wrapperc.eq("type", "通知公告");

PageHelper.startPage(pageNum, pageSize);
List<Schoolnews> schoolnewsc = schoolnewsMapper.selectList(wrapperc);
model.addAttribute("tongzhinews", schoolnewsc);

//实现倒序输出(电子校报)
QueryWrapper<Schoolnews> wrapperd = new QueryWrapper<>();
wrapperd.orderByDesc("id");
wrapperd.eq("emo", 3);
wrapperd.eq("type", "电子校报");

PageHelper.startPage(pageNum, pageSize);
List<Schoolnews> schoolnewsd = schoolnewsMapper.selectList(wrapperd);
model.addAttribute("dianzinews", schoolnewsd);

//实现倒序输出(媒体)
QueryWrapper<Schoolnews> wrappere = new QueryWrapper<>();
wrappere.orderByDesc("id");
wrappere.eq("emo", 3);
wrappere.eq("type", "媒体");

PageHelper.startPage(pageNum, pageSize);
List<Schoolnews> schoolnewse = schoolnewsMapper.selectList(wrappere);
model.addAttribute("meitinews", schoolnewse);
return "/snews/index";
}

点击查看具体新闻

——SnewsController

1
2
3
4
5
6
@GetMapping("/indnewss/{id}")
public String indpageshouw(@PathVariable("id") String id, Model model) {
Schoolnews schoolnews = schoolnewsMapper.selectById(id);
model.addAttribute("news", schoolnews);
return "snews/newshows";
}

查看某类全部新闻

——SnewsController

1
2
3
4
5
6
7
8
9
@GetMapping("/newlis/{type}")
public String newliss(@PathVariable("type") String type, Model model) {
QueryWrapper<Schoolnews> new233 = new QueryWrapper<>();
new233.eq("type", type);
List<Schoolnews> schoolnews = schoolnewsMapper.selectList(new233);
model.addAttribute("type", type);
model.addAttribute("news", schoolnews);
return "snews/newslists";
}

论坛部分

创建实体

①.帖子(News)

1
2
3
4
5
6
7
8
9
10
11
12
13
@Data
@NoArgsConstructor
@AllArgsConstructor
public class News {
int id;
String user;
String title;
String news;
String type;

@TableField(fill= FieldFill.INSERT)
Date time;
}

②.用户(User)

1
2
3
4
5
6
7
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
String id;
String password;
}

③.评论(Log)

1
2
3
4
5
6
7
8
9
10
11
12
13
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Log {
int id;
int lzid;
String loguser;
String title;
String log;

@TableField(fill= FieldFill.INSERT)
Date time;
}

④.管理员(Admin)

1
2
3
4
5
6
7
8
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Admin {
String id;
String password;
int level;
}

配置mapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Mapper
public interface NewsMapper extends BaseMapper<News> {
}

@Mapper
public interface LogMapper extends BaseMapper<Log> {
}

@Mapper
public interface AdminMapper extends BaseMapper<Admin> {
}

@Mapper
public interface UserMapper extends BaseMapper<User> {

}

登录,注册,退出功能

——LoginController

用户或管理员登录

不同的角色跳转的页面不同——LoginController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@RequestMapping("/login")
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
Model model
,HttpSession session
) {

//登录实现
User user = userMapper.selectById(username);
if(username.equals("admin")&&password.equals("123")){//管理员登录
session.setAttribute("loginUser", username);
return "redirect:/userlist";
}else {//普通用户登录
if (user != null) {
if (password.equals(user.getPassword())) {
session.setAttribute("loginUser", username);
//登录成功
return "redirect:/Main";
} else {
model.addAttribute("msg", "密码错误");
return "loginl";
}

} else {
model.addAttribute("msg", "用户不存在");
return "loginl";
}
}

用户或管理员注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@RequestMapping("/rege")
public String save (User user,Model model){
//添加的操作
User user233 = userMapper.selectById(user.getId());
if (user.getId().equals("admin")) {
model.addAttribute("msg", "不准注册管理员帐号");
return "register";
} else {
if (user233 == null) {
userMapper.insert(user); //调用底层业务保存用户
model.addAttribute("msg", "注册成功,请返回登录");
return "loginl";
} else {

model.addAttribute("msg", "用户已存在");
return "register";

}
}

}

用户或管理员登录

1
2
3
4
5
@RequestMapping("/user/logout")
public String logout(HttpSession session){
session.invalidate();
return "redirect:/login.html";
}

用户功能

查看不同板块帖子

以综合板块和匿名板块为例,综合板块除了匿名板块包括日常,学习,围炉夜话和询问板块

——NewsController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RequestMapping("/zonghe")
public String zonghe(Model model
, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum
, @RequestParam(defaultValue = "10", value = "pageSize") Integer pageSize){
//实现按照时间倒序输出
QueryWrapper<News> newsQueryWrapper = new QueryWrapper<>();
newsQueryWrapper.orderByDesc("time");
newsQueryWrapper.ne("type","匿名");
//分页
PageHelper.startPage(pageNum, pageSize);
List<News> news = newsMapper.selectList(newsQueryWrapper);
PageInfo<News> newsPageInfo = new PageInfo<>(news);
model.addAttribute("news",news);
model.addAttribute("pageInfo", newsPageInfo);
return "News/zonghe";
}

匿名板块

——NewsController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RequestMapping("/niming")
public String niming(Model model
, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum
, @RequestParam(defaultValue = "10", value = "pageSize") Integer pageSize){
//实现倒序输出
QueryWrapper<News> newsQueryWrapper = new QueryWrapper<>();
newsQueryWrapper.orderByDesc("time");
newsQueryWrapper.eq("type","匿名");
//分页
PageHelper.startPage(pageNum, pageSize);
List<News> news = newsMapper.selectList(newsQueryWrapper);
PageInfo<News> newsPageInfo = new PageInfo<>(news);
model.addAttribute("news",news);
model.addAttribute("pageInfo", newsPageInfo);
return "News/niming";
}

查看帖子详情

——NewsController

1
2
3
4
5
6
7
8
9
10
@GetMapping("/news/{id}")
public String newsshouw(@PathVariable("id")String id,Model model){
News newz = newsMapper.selectById(id);
HashMap<String, Object> map = new HashMap<>();
map.put("lzid",id);
List<Log> logs = logMapper.selectByMap(map);
model.addAttribute("logs",logs);
model.addAttribute("news",newz);
return "News/zshow";
}

跟帖评论

——NewsController

1
2
3
4
5
6
7
8
9
@RequestMapping("/newslog")
public String logsub(Log log){
if(log.getTitle().isEmpty() || log.getLog().isEmpty()){
return "redirect:/news/"+log.getLzid();
}else {
logMapper.insert(log);
return "redirect:/news/"+log.getLzid();
}
}

发布帖子

——NewsController

1
2
3
4
5
6
7
8
9
10
11
12
13
@RequestMapping("/newssubmit")
public String newssub(News news,Model model){
System.out.println(news);
if (news.getTitle().isEmpty()){
model.addAttribute("msg","标题写点东西再发布!");
return "fail";
}else {

newsMapper.insert(news);
model.addAttribute("msg","发帖成功");
return "succ";
}
}

用户改自己密码

——UserController

1
2
3
4
5
6
7
@GetMapping("/useru/{id}")
public String editu(@PathVariable("id")String id,Model model){
//查出原先的数据
User user = userMapper.selectById(id);
model.addAttribute("user",user);
return "user/editu";
}

管理员功能

用户管理

1.查找用户

——UserController

1
2
3
4
5
6
7
8
9
10
11
12
13
@RequestMapping("/quary")
public String qula(String name,Model model, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum, @RequestParam(defaultValue = "10", value = "pageSize") Integer pageSize){
QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();
objectQueryWrapper.like("id",name);
PageHelper.startPage(pageNum, pageSize);
List<User> users = userMapper.selectList(objectQueryWrapper);
PageInfo<User> pageInfo = new PageInfo<>(users);
model.addAttribute("user",users);
model.addAttribute("name",name);
model.addAttribute("pageInfo", pageInfo);

return "user/userlista";
}

2.显示用户列表

——UserController

1
2
3
4
5
6
7
8
9
10
11
12
13
@RequestMapping("/userlist")
public String userlist(Model model, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum, @RequestParam(defaultValue = "10", value = "pageSize") Integer pageSize){


PageHelper.startPage(pageNum, pageSize);
List<User> users = userMapper.selectList(null);
PageInfo<User> pageInfo = new PageInfo<>(users);

model.addAttribute("user",users);
model.addAttribute("pageInfo", pageInfo);

return "user/userlist";
}

3.维护用户信息

——UserController

1
2
3
4
5
6
7
8
9
10
11
12
@GetMapping("/user/{id}")
public String edit(@PathVariable("id")String id,Model model){//回显用户信息
//查出原先的数据
User user = userMapper.selectById(id);
model.addAttribute("user",user);
return "user/edit";
}
@PostMapping("/edituser")
public String edit(User user){//修改信息
userMapper.updateById(user);
return "redirect:/userlist";
}

4.删除用户

——UserController

1
2
3
4
5
@GetMapping("/userdel/{id}")
public String del(@PathVariable("id")String id){
userMapper.deleteById(id);
return "redirect:/userlist";
}
帖子管理

1.查找帖子

——NewsController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RequestMapping("/quarynew")
public String qula(String name,Model model, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum, @RequestParam(defaultValue = "10", value = "pageSize") Integer pageSize){

QueryWrapper<News> objectQueryWrapper = new QueryWrapper<>();
objectQueryWrapper.like("title",name);

PageHelper.startPage(pageNum, pageSize);
List<News> news = newsMapper.selectList(objectQueryWrapper);
PageInfo<News> pageInfo = new PageInfo<>(news);

model.addAttribute("news",news);
model.addAttribute("name",name);
model.addAttribute("pageInfo", pageInfo);

return "user/newsb";
}

2.查看帖子列表

——NewsController

1
2
3
4
5
6
7
8
9
10
@RequestMapping("/newsa")
public String newsa(Model model, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum, @RequestParam(defaultValue = "10", value = "pageSize") Integer pageSize){
PageHelper.startPage(pageNum, pageSize);
List<News> news = newsMapper.selectList(null);
PageInfo<News> pageInfo = new PageInfo<>(news);

model.addAttribute("news",news);
model.addAttribute("pageInfo", pageInfo);
return "user/newsa";
}

3.查看具体帖子以及评论

——NewsController

1
2
3
4
5
6
7
8
9
10
@GetMapping("/newsa/{id}")
public String newsashow(@PathVariable("id")String id,Model model){
News newz = newsMapper.selectById(id);
HashMap<String, Object> map = new HashMap<>();
map.put("lzid",id);
List<Log> logs = logMapper.selectByMap(map);
model.addAttribute("logs",logs);
model.addAttribute("news",newz);
return "user/newsashow";
}

4.删除帖子

——NewsController

1
2
3
4
5
6
7
8
@GetMapping("/newsadel/{id}")
public String del(@PathVariable("id")String id){
newsMapper.deleteById(id);
HashMap<String, Object> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("lzid",id);
logMapper.deleteByMap(objectObjectHashMap);
return "redirect:/newsa";
}

后台管理部分

管理员有四个身份:总管理,一级审核,二级审核,写手。每个身份登录可以看到不同的界面。

审核部分

1.提交新闻

总管理,一级审核,二级审核,写手都可以发布新闻

——SchoolnewsController

1
2
3
4
5
6
7
8
9
10
11
@RequestMapping("/snewspost")
public String snewpost(Schoolnews schoolnews,Model model){
if(schoolnews.getTitle().isEmpty() || schoolnews.getWord().isEmpty()){
model.addAttribute("msg","请保证标题或内容不为空。");
return "admin/postnew";
}else {
schoolnewsMapper.insert(schoolnews);
model.addAttribute("msg","发布成功,您的投稿已进入审核队列。");
return "admin/postnew";
}
}

2.一级审核

只能审核写手写的新闻

——SchoolnewsController

1
2
3
4
5
6
7
8
9
10
11
12
13
@RequestMapping("/newjud")
public String newjud(Model model, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum, @RequestParam(defaultValue = "10", value = "pageSize") Integer pageSize){
QueryWrapper<Schoolnews> newsQueryWrapper = new QueryWrapper<>();
newsQueryWrapper.orderByDesc("id");
newsQueryWrapper.gt("wlevel",3);//大于
newsQueryWrapper.eq("emo",1);
PageHelper.startPage(pageNum, pageSize);
List<Schoolnews> schoolnews = schoolnewsMapper.selectList(newsQueryWrapper);
PageInfo<Schoolnews> pageInfo = new PageInfo<>(schoolnews);
model.addAttribute("news",schoolnews);
model.addAttribute("pageInfo", pageInfo);
return "admin/juda";
}

3.二级审核

能审核写手和一级审核写的新闻

——SchoolnewsController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RequestMapping("/newjudb")
public String newjudb(Model model, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum, @RequestParam(defaultValue = "10", value = "pageSize") Integer pageSize){
//实现倒序输出
QueryWrapper<Schoolnews> newsQueryWrapper = new QueryWrapper<>();
newsQueryWrapper.orderByDesc("id");
//选择等级为2的
newsQueryWrapper.gt("wlevel",2);
newsQueryWrapper.eq("emo",1);
PageHelper.startPage(pageNum, pageSize);
List<Schoolnews> schoolnews = schoolnewsMapper.selectList(newsQueryWrapper);
PageInfo<Schoolnews> pageInfo = new PageInfo<>(schoolnews);
model.addAttribute("news",schoolnews);
model.addAttribute("pageInfo", pageInfo);
return "admin/judb";
}

4.三级审核

能审核所有人写的新闻

——SchoolnewsController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RequestMapping("/newjudd")
public String newjudc(Model model, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum, @RequestParam(defaultValue = "10", value = "pageSize") Integer pageSize){
//实现倒序输出
QueryWrapper<Schoolnews> newsQueryWrapper = new QueryWrapper<>();
newsQueryWrapper.orderByDesc("id");
//选择等级为2的
newsQueryWrapper.gt("wlevel",1);
newsQueryWrapper.eq("emo",1);
PageHelper.startPage(pageNum, pageSize);
List<Schoolnews> schoolnews = schoolnewsMapper.selectList(newsQueryWrapper);
PageInfo<Schoolnews> pageInfo = new PageInfo<>(schoolnews);
model.addAttribute("news",schoolnews);
model.addAttribute("pageInfo", pageInfo);
return "admin/judd";
}

管理部分

管理员

显示管理员列表

——AdminController

1
2
3
4
5
6
7
8
9
@RequestMapping("/adlist")
public String adlist(Model model, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum, @RequestParam(defaultValue = "10", value = "pageSize") Integer pageSize){
PageHelper.startPage(pageNum, pageSize);
List<Admin> users = adminMapper.selectList(null);
PageInfo<Admin> pageInfo = new PageInfo<>(users);
model.addAttribute("user",users);
model.addAttribute("pageInfo", pageInfo);
return "admin/adlist";
}

添加管理员

——AdminController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//前往增加管理员页面 
@RequestMapping("/addad")
public String savead(){
return "admin/addadmin";
}
//接收添加管理员请求
@PostMapping("/addad")
public String save (Admin admin,Model model){
//添加的操作
Admin ad233 = adminMapper.selectById(admin.getId());
if (ad233 != null){
model.addAttribute("msg","该昵称已存在");
return "admin/addadmin";
}else {
if (admin.getId().isEmpty() || admin.getPassword().isEmpty()){
model.addAttribute("msg","昵称和密码不为空");
return "admin/addadmin";
}else {

System.out.println("save-->"+admin);
adminMapper.insert(admin); //调用底层业务保存员工信息
return "redirect:/adlist";
}
}

}

维护管理员

——AdminController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//修改管理员时填的默认值(数据回显) 跳往admin/editad.html
@GetMapping("/aded/{id}")
public String edit(@PathVariable("id") String id, Model model){
//先查出原来的数据
Admin admin = adminMapper.selectById(id);
model.addAttribute("user",admin);
return "admin/editad";
}

@PostMapping("/edad")
public String edit(Admin admin){
adminMapper.updateById(admin);
return "redirect:/adlist";
}

删除管理员

——AdminController

1
2
3
4
5
@GetMapping("/delad/{id}")
public String del(@PathVariable("id")String id){
adminMapper.deleteById(id);
return "redirect:/adlist";
}
论坛

显示论坛列表

——AdminController

1
2
3
4
5
6
7
8
9
10
@RequestMapping("/newslist")
public String newsa(Model model, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum, @RequestParam(defaultValue = "10", value = "pageSize") Integer pageSize){
PageHelper.startPage(pageNum, pageSize);
List<News> news = newsMapper.selectList(null);
PageInfo<News> pageInfo = new PageInfo<>(news);
model.addAttribute("news",news);
model.addAttribute("pageInfo", pageInfo);

return "admin/newslist";
}

查看具体帖子

——AdminController

1
2
3
4
5
6
7
8
9
10
@GetMapping("/newslist/{id}")
public String newsashow(@PathVariable("id")String id, Model model){
News newz = newsMapper.selectById(id);
HashMap<String, Object> map = new HashMap<>();
map.put("lzid",id);
List<Log> logs = logMapper.selectByMap(map);
model.addAttribute("logs",logs);
model.addAttribute("news",newz);
return "admin/adnewsshow";
}

删除帖子

——AdminController

1
2
3
4
5
6
7
8
@GetMapping("/newsqdel/{id}")
public String delnews(@PathVariable("id")String id){
newsMapper.deleteById(id);
HashMap<String, Object> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("lzid",id);
logMapper.deleteByMap(objectObjectHashMap);
return "redirect:/newslist";
}
全部新闻

查看新闻列表

——SchoolnewsController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RequestMapping("/listed")
public String judlists(Model model, @RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum, @RequestParam(defaultValue = "10", value = "pageSize") Integer pageSize){

//实现倒序输出
QueryWrapper<Schoolnews> newsQueryWrapper = new QueryWrapper<>();
newsQueryWrapper.orderByDesc("id");
//选择等级为3的
newsQueryWrapper.ge("emo",1);//大于等于
PageHelper.startPage(pageNum, pageSize);
List<Schoolnews> schoolnews = schoolnewsMapper.selectList(newsQueryWrapper);
PageInfo<Schoolnews> pageInfo = new PageInfo<>(schoolnews);
model.addAttribute("news",schoolnews);
model.addAttribute("pageInfo", pageInfo);
return "admin/judc";
}

查看具体新闻

——SchoolnewsController

1
2
3
4
5
6
@GetMapping("/pageshowc/{id}")
public String pageshouwc(@PathVariable("id")String id, Model model){
Schoolnews schoolnews = schoolnewsMapper.selectById(id);
model.addAttribute("news",schoolnews);
return "admin/pageshowjudc";
}

删除新闻

——SchoolnewsController

1
2
3
4
5
@GetMapping("/delsnews/{id}")
public String nessdel(@PathVariable("id")String id){
schoolnewsMapper.deleteById(id);
return "redirect:/admin";
}

关键技术总结

一.Spring Boot集成Thymeleaf模板引擎

Thymeleaf 介绍

Thymeleaf 是适用于 Web 和独立环境的现代服务器端 Java 模板引擎。Thymeleaf 的主要目标是为您的开发工作流程带来优雅的自然模板 - 可以在浏览器中正确显示的HTML,也可以用作静态原型,从而在开发团队中实现更强大的协作。

Thymeleaf 使用

1.导入依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

2.在 html 页面上如果要使用 thymeleaf 模板

1
<html xmlns:th="http://www.thymeleaf.org">

3.thymeleaf 相关配置

因为 Thymeleaf 中已经有默认的配置了,我们不需要再对其做过多的配置,有一个需要注意一下,Thymeleaf 默认是开启页面缓存的,所以在开发的时候,需要关闭这个页面缓存,配置如下。

1
2
3
spring:
thymeleaf:
cache: false #关闭缓存

4.在 thymeleaf 模板中,使用 th:object="${}" 来获取对象信息,然后在表单里面可以有三种方式来获取对象属性。

1
2
3
使用 th:value="*{属性名}"
使用 th:value="${对象.属性名}",对象指的是上面使用 th:object 获取的对象
使用 th:value="${对象.get方法}",对象指的是上面使用 th:object 获取的对象

5.thymeleaf 处理list

1
2
3
4
5
6
7
8
9
10
@GetMapping("/getList")
public String getList(Model model) {
Blogger blogger1 = new Blogger(1L, "好富帅", "123456");
Blogger blogger2 = new Blogger(2L, "达人课", "123456");
List<Blogger> list = new ArrayList<>();
list.add(blogger1);
list.add(blogger2);
model.addAttribute("list", list);
return "list";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<title>博主信息</title>
</head>
<body>
<form action="" th:each="blogger : ${list}" >
用户编号:<input name="id" th:value="${blogger.id}"/><br>
用户姓名:<input type="text" name="password" th:value="${blogger.name}"/><br>
登录密码:<input type="text" name="username" th:value="${blogger.getPass()}"/>
</form>
</body>
</html>

可以看出,其实和处理单个对象信息差不多,Thymeleaf 使用 th:each 进行遍历,${} 取 model 中传过来的参数,然后自定义 list 中取出来的每个对象,这里定义为 blogger。表单里面可以直接使用 ${对象.属性名} 来获取 list 中对象的属性值,也可以使用 ${对象.get方法} 来获取,这点和上面处理对象信息是一样的,但是不能使用 *{属性名} 来获取对象中的属性,thymeleaf 模板获取不到。

二.MybatisPlus

简介

概述:

MyBatis-Plus (简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

MybatisPlus特性:

-
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

使用

1.创建数据库并创建对应的实体类

2.导入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>

<!--MybatisPlus-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

3.配置配置文件

1
2
3
4
5
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/hello?useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.jdbc.Driver

1
2
3
4
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/hello?useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

4.建立mapper并在主启动类上添加包扫描注解

1
2
3
4
@Mapper
public interface UserMapper extends BaseMapper<User> {

}

5.配置日志输出

1
2
3
#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

条件构造器Wrapper方法

  • gt:大于,ge:大于等于,lt:小于,le:小于等于
  • eq:等于,ne:不等于
  • between:在值1和值2之间,notBetween:不在值1和值2之间
  • like:’%值%’,notLike:’%值%’,likeLeft:’%值’,likeRight:’值%’
  • isNull:字段 IS NULL,isNotNull:字段 IS NOT NULL
  • in:字段 IN (v0, v1, …),notIn:字段 NOT IN (value.get(0), value.get(1), …)
  • 主动调用or表示紧接着下一个方法不是用and连接!(不调用or则默认为使用and连接)
  • orderByAsc:升序:ORDER BY 字段, … ASC,orderByDesc:降序:ORDER BY 字段, … DESC
  • inSql:字段 IN ( sql语句 ),notInSql:字段 NOT IN ( sql语句 )
  • exists:拼接 EXISTS ( sql语句 ),notExists:拼接 NOT EXISTS ( sql语句 )

使用代码生成器

代码生成器简介

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

代码生成器配置

添加依赖

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.0</version>
</dependency>

<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>

编写配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class CodeGenerator {


public static void main(String[] args) {
//创建代码生成器
AutoGenerator mpg = new AutoGenerator();

//全局配置
GlobalConfig gc = new GlobalConfig();
//获取当前系统目录
String projectPath = System.getProperty("user.dir");

gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("dong"); //生成作者注释
gc.setOpen(false); //生成后是否打开资源管理器
gc.setFileOverride(false); //重新生成时文件是否覆盖
gc.setServiceName("%sService"); //去掉Service接口的首字母I
gc.setIdType(IdType.ID_WORKER); //主键策略
gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
gc.setSwagger2(false);//开启Swagger2模式

mpg.setGlobalConfig(gc);

// 3、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/mp?serverTimezone=GMT%2B8"); //url
dsc.setDriverName("com.mysql.cj.jdbc.Driver"); //数据库驱动
dsc.setUsername("root"); //数据库账号
dsc.setPassword("root"); //数据库密码
dsc.setDbType(DbType.MYSQL); //数据库类型
mpg.setDataSource(dsc);

// 4、包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("test"); //模块名,可以不设置
pc.setParent("cn.dong"); //放在哪个包下
pc.setController("controller");
pc.setEntity("entity");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);

// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("employee");//对哪一张表生成代码
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀

strategy.setLogicDeleteFieldName("deleted"); //逻辑删除字段设置

strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作

strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符
mpg.setStrategy(strategy);

//执行
mpg.execute();

}
}

页面展示

项目首页

image-20230605212729213

新闻页面

新闻主页

image-20230605212855426

新闻页面

image-20230605215117723

查看所有新闻

image-20230605215204969

论坛页面

论坛登录

image-20230605215518012

论坛注册

image-20230605215555453

论坛主页(用户登录)

image-20230605215650590

查看论坛

image-20230605215743006

发表问题

image-20230605220415211

追加评论

image-20230605220457928

用户自行修改密码

image-20230605215825152

论坛主页(管理员登录)

image-20230605221437129

新闻管理

image-20230605221628864

后台页面

后台管理登录

image-20230605221728184

写手页面

image-20230605221825227

一级审核

image-20230605222248233

二级审核

image-20230605222332608

总管理

image-20230605223024252

管理员列表

image-20230605223055965

维护管理员

image-20230605223123239

论坛维护

image-20230605223235496

已发布主页新闻维护页面

image-20230605223342105

项目源码(数据库)

$$
链接:https://pan.baidu.com/s/1VxRY67cDdecjdK5pjCrnVA?pwd=a4kd
提取码:a4kd
$$