文章目录
项目搭建
采用springboot快速构建项目,导入相关包完成整合即可
配置文件中加上这个
server.servlet.context-path=/community
访问项目时需要多加一级/community
spring
springmvc
牛客论坛项目结构和studyfun类似,采用mvc模式,项目中有很多东西都是当时实习的时候不太懂的,借此机会学习一下,希望以后实习时公司的老项目自己也可以维护
model的使用
mvc在三层架构的控制层,model相当于一个容器,通过model.addAttribute()方法,往容器里面去存放相应的数据,然后前端通过model就可以取里面的值拼接在html页面上完成数据展示
参数响应方式
路径参数
RequestMapping里需要写个占位符,参数前需要加个路径注解
@RestController
@RequestMapping("/alpha")
public class AlphaController {
@RequestMapping("/hello/{id}")
public String sayHello(@PathVariable("id") int id) {
return "Hello Springboot"+id;
}
}
访问结果
普通参数
声明什么参数,在地址栏里加上?参数名=xxx,即可完成参数传递
关于返回值
前后端分离的方式中后端只需要把数据封装在JSON中进行传输。在mvc里,如果方法不加ResponseBody且返回类型为String则后端return的是静态资源中的html
@Controller
public class HomeController {
@Autowired
private UserService userService;
@Autowired
private DiscussPostService discussPostService;
@RequestMapping(path = "/index",method = RequestMethod.GET)
public String getIndex(Model model, Page page){
return "/index";
}
}
在地址栏里通过http://localhost:8080/community/index访问直接就跳转页面访问了
mybatis
有一些小的操作时间太久都忘记了,也有几个是在公司读业务代码时百思不得其解的,现在都记录在这儿
resultType
通俗的说,就是mapper接口查询后的返回值类型,像Java中常见的类型,比如int这一类的可以不声明,但是像自己定义的实体类需要去声明,声明时注意一定要把包的路径写全(一般会自动提示),不然mybatis会报错说找不到类。
parameterType
这个对应的是mapper接口里面的参数,如果你的参数是简单类型,比如int\double\string等,就不需要声明了,但是如果传的是自定义的实体类型,需要把parameterType指定一下,要把包的全路径写出来。如下:
keyProperty
这个一般是插入操作时会用,因为现在数据库主键一般是自增长,而且是由数据库自身所实现的,这个属性的含义就是mybatis去操作数据库增加一条数据,然后如果需要获取这个新增行的主键id的话, 我们可以通过keyProperty设置到我们实体类的主键属性上去。解决的问题就是在插入数据主键自增时获取主键值。
useGeneratedKeys
常与keyProperty联合使用
项目调试
服务端debug
已熟练掌握
日志文件相关
首页开发
页面逻辑
主要逻辑就是查询discuss_post表和user表,但是采用的逻辑有两种,一种是dao层进行联表查询,一种是业务层处理,这里采用第二种。
我们需要往视图层里面去存一个装list的map即可,每个map里面有user和对应的post数据。
分页逻辑(较常用)
分页的sql语句比较简单,在sql子句后面跟个limit即可,通常是limit offset,size,这里的offset代表当前页的起始行,size代表每页的条目数,计算当前页的起始行公式是 offset = (current-1)*size,current代表当前页,比如第2页、3页、4页等
封装Page
分页需要很多信息,通常公司都会有自己封装的Page,后悔自己没有多研究公司代码
/**
* 封装分页相关的信息.
*/
public class Page {
// 当前页码
private int current = 1;
// 显示上限
private int limit = 10;
// 数据总数(用于计算总页数)
private int rows;
// 查询路径(用于复用分页链接)
private String path;
public int getCurrent() {
return current;
}
public void setCurrent(int current) {
if (current >= 1) {
this.current = current;
}
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
if (limit >= 1 && limit <= 100) {
this.limit = limit;
}
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
if (rows >= 0) {
this.rows = rows;
}
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
/**
* 获取当前页的起始行
*
* @return
*/
public int getOffset() {
// current * limit - limit
return (current - 1) * limit;
}
/**
* 获取总页数
*
* @return
*/
public int getTotal() {
// rows / limit [+1]
if (rows % limit == 0) {
return rows / limit;
} else {
return rows / limit + 1;
}
}
/**
* 获取起始页码
*
* @return
*/
public int getFrom() {
int from = current - 2;
return from < 1 ? 1 : from;
}
/**
* 获取结束页码
*
* @return
*/
public int getTo() {
int to = current + 2;
int total = getTotal();
return to > total ? total : to;
}
}
开发
mapper
这里在dao层,我们查询分页,后期有可能用到userId,因此先写上,offset和limit对应的就是我们sql语句要用到的offset和limit,因此dao层比较接近sql语句
public List<DiscussPost> selectDiscussPosts(int userId,int offset,int limit);
<select id="selectDiscussPosts" resultType="com.nowcorder.community.entity.DiscussPost">
select <include refid="selectFields"></include>
from discuss_post
where status!=2
<if test="userId!=0">
and user_id = #{userId}
</if>
order by type desc,create_time desc
limit #{offset},#{limit}
</select>
这里需要注意的是,分页在排序之后,如果位置错了会sql语法错
service
正常返回list
controller
我们拿到装帖子的List后需要查询出每个帖子对应的user信息,然后将其装到map里,一个map对应一个user和post,然后用一个List装好这些map,最后给model就完成了数据封装
@Controller
public class HomeController {
@Autowired
private UserService userService;
@Autowired
private DiscussPostService discussPostService;
@RequestMapping(path = "/index",method = RequestMethod.GET)
public String getIndex(Model model, Page page){
int rows = discussPostService.findTotal(0);
page.setRows(rows);
page.setPath("/index");
List<DiscussPost> list = discussPostService.findDiscussPost(0, page.getOffset(), page.getLimit());
ArrayList<Map<String, Object>> discussPosts = new ArrayList<>();
if(list!=null){
for (DiscussPost post : list) {
User user = userService.selectById(post.getUserId());
HashMap<String, Object> map = new HashMap<>();
map.put("post",post);
map.put("user",user);
discussPosts.add(map);
}
}
model.addAttribute("discussPosts",discussPosts);
return "/index";
}
}