SpringBoot(4) - 视图渲染技术
1.Freemarker简介及入门
学习网址
http://freemarker.foofun.cn/
1.1首先,新建一个模块
1.2预加载依赖
1.3添加application.yml的配置
mybatis:
mapper-locations: classpath:mappers/**/*.xml
type-aliases-package: com.hyx.springboot04.entity
logging:
level:
com.hyx.springboot04: debug
server:
port: 8080
spring:
application:
name: springboot04
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
name: defaultDataSource
password: 123456
url: jdbc:mysql://localhost:3306/ssmbuild?useUnicode=true&characterEncoding=UTF-8
username: root
freemarker:
cache: false
charset: utf-8
expose-request-attributes: true
expose-session-attributes: true
suffix: .ftl
template-loader-path: classpath:/templates/
resources:
static-locations: classpath:/static/**
1.4构建freemarker的模板
1.5现在在templete新建一个index.ftl文件
1.6新建一个controller层
1.7测试一下成功
2.FreeMarker的语法
2.1 语法
2.2新建一个实体类
package com.hyx.springboot04.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private int id;
private String name;
}
2.3修改index.ftl
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>语法测试</title>
</head>
<body>
<p>取值</p>
${name }
<p>条件</p>
<#if sex== 'nv'>
女
<#elseif sex=='nan'>
男
<#else>
南通
</#if>
<p>循环</p>
<#list user as u>
${u.id }=======${u.name }
</#list>
<p>include</p>
<#include '/common.ftl'>
<p>局部变量和全局变量</p>
${ctx}
<hr>
${ctx2}
</body>
</html>
2.4新建一个common.ftl
这是顶部导航栏信息
项目名称
局部变量
<#assign ctx>
${springMacroRequestContext.contextPath}
</#assign>
全局变量
<#global ctx2>
${springMacroRequestContext.contextPath}
</#global>
2.5修改controller
package com.hyx.springboot04.web;
import com.hyx.springboot04.entity.User;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
@Controller
public class IndexController {
@GetMapping("/")
public String index(HttpServletRequest request) {
System.out.println("come on....index");
request.setAttribute("name", "zs");
request.setAttribute("sex", "gay");
request.setAttribute("user", Arrays.asList(
new User(1, "张三"),
new User(2, "李四"),
new User(3, "王五")));
//suffix: .ftl
//template-loader-path: classpath:/templates/
//===> templates/index.ftl
return "index";
}
}
2.6重启测试
发现取值都取到
2.7注意问题,为空
如果freemarker去取值的时候,那个值根本不存在,也就是为空的时候会报错,那么如何去避免报错呢?在后面加!
,这样如果没有值的话就不显示
示例
改变
这样为空的就不会报错啦
这下面是举例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h2>1.取值</h2>
<h3>1.1. 提供默认值</h3>
<#--报错-->
<#--${uname} -->
<#--不报错,但是页面无内容-->
<#--${uname !}-->
<#--给值设置一个默认值-->
${uname! '无名'}
<h3>1.2. 对null值先进行判断</h3>
<p>1)exists用在逻辑判断;</p>
<#if uname?exists>
${uname}
</#if>
<br>
<p>2)??是判断对象是否为空</p>
<#if uname??>
${uname}
</#if>
<br>
<p>3)if_exists用来打印东西</p>
${uname?if_exists}
<br>
<h3>2.条件</h3>
<#if sex=='nv'>
女
<#elseif sex='nan'>
男
<#else>
未知
</#if>
<br>
<h3>3.循环</h3>
<p>1)取出数组中的元素</p>
<#list arr as a>
${a}==
</#list>
<br>
<p>2)取出集合中的对象(注:访问的类要被public所修饰)</p>
<#list lst as item>
${item.id} : ${item.name} <br>
</#list>
<h3>4 include</h3>
<#include "/common.ftl" >
<h3>5 局部变量(assign)/全局变量(global)</h3>
${ctx}:${ctx2}
</body>
</html>
3.FreeMarker的综合案例
3.1导入相关表数据
运行一下sql文件,略
添加分页配置
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
在application.yml中添加如下配置
pagehelper:
reasonable: true
supportMethodsArguments: true
page-size-zero: true
helper-dialect: mysql
3.2建立目录结构
entity/mapper/contorller/service
3.2.1 entity导入Clazz.java类
package com.hyx.springboot04.entity;
public class Clazz {
protected Integer cid;
protected String cname;
protected String cteacher;
protected String pic;
public Clazz(Integer cid, String cname, String cteacher, String pic) {
this.cid = cid;
this.cname = cname;
this.cteacher = cteacher;
this.pic = pic;
}
public Clazz() {
super();
}
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public String getCteacher() {
return cteacher;
}
public void setCteacher(String cteacher) {
this.cteacher = cteacher;
}
public String getPic() {
return pic;
}
public void setPic(String pic) {
this.pic = pic;
}
}
3.2.2导入ClazzBiz.java类
package com.hyx.springboot04.biz;
import com.hyx.springboot04.entity.Clazz;
import com.hyx.springboot04.util.PageBean;
import java.util.List;
import java.util.Map;
public interface ClazzBiz {
int deleteByPrimaryKey(Integer cid);
int insert(Clazz record);
int insertSelective(Clazz record);
Clazz selectByPrimaryKey(Integer cid);
int updateByPrimaryKeySelective(Clazz record);
int updateByPrimaryKey(Clazz record);
List<Clazz> listPager(Clazz clazz, PageBean pageBean);
List<Map> listMapPager(Clazz clazz, PageBean pageBean);
}
3.2.3添加ClazzImpl实现类
package com.hyx.springboot04.biz.impl;
import com.hyx.springboot04.biz.ClazzBiz;
import com.hyx.springboot04.entity.Clazz;
import com.hyx.springboot04.mapper.ClazzMapper;
import com.hyx.springboot04.util.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* @author小李飞刀
* @site www.javaxl.com
*/
@Service
public class ClazzBizImpl implements ClazzBiz {
@Autowired
private ClazzMapper clazzMapper;
@Override
public int deleteByPrimaryKey(Integer cid) {
System.out.println("不做任何操作...");
return clazzMapper.deleteByPrimaryKey(cid);
// return 0;
}
@Override
public int insert(Clazz record) {
return clazzMapper.insert(record);
}
@Override
public int insertSelective(Clazz record) {
return clazzMapper.insertSelective(record);
}
@Override
public Clazz selectByPrimaryKey(Integer cid) {
return clazzMapper.selectByPrimaryKey(cid);
}
@Override
public int updateByPrimaryKeySelective(Clazz record) {
return clazzMapper.updateByPrimaryKeySelective(record);
}
@Override
public int updateByPrimaryKey(Clazz record) {
return clazzMapper.updateByPrimaryKey(record);
}
@Override
public List<Clazz> listPager(Clazz clazz, PageBean pageBean) {
return clazzMapper.listPager(clazz);
}
@Override
public List<Map> listMapPager(Clazz clazz, PageBean pageBean) {
if(true)
throw new RuntimeException("查询班级信息异常,异常存在于ClazzBizImpl.list。。。。");
return clazzMapper.listMapPager(clazz);
}
}
3.2.4添加ClazzContorller类
package com.hyx.springboot04.controller;
import com.hyx.springboot04.biz.ClazzBiz;
import com.hyx.springboot04.entity.Clazz;
import com.hyx.springboot04.util.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* @author小李飞刀
* @site www.javaxl.com
*/
@Controller
@RequestMapping("/clz")
public class ClazzController {
@Autowired
private ClazzBiz clazzBiz;
@RequestMapping("/list")
public String list(Clazz clazz, HttpServletRequest request){
System.out.println("我添加了 新的代码,终于不重启了....");
PageBean pageBean = new PageBean();
pageBean.setRequest(request);
List<Clazz> lst = this.clazzBiz.listPager(clazz, pageBean);
//String pagestr = PageFreemarker.toHTML(pageBean);
request.setAttribute("lst",lst);
request.setAttribute("pageBean",pageBean);
//request.setAttribute("pagestr",pagestr);
return "clz/clzList";
}
@RequestMapping("/toEdit")
public String toEdit(Clazz clazz, HttpServletRequest request){
Integer cid = clazz.getCid();
// 传递的id代表了修改,没传代表新增
if(cid != null){
List<Clazz> lst = this.clazzBiz.listPager(clazz, null);
request.setAttribute("b",lst.get(0));
}
return "clz/clzEdit";
}
@RequestMapping("/add")
public String add(Clazz clazz){
this.clazzBiz.insertSelective(clazz);
return "redirect:/clz/list";
}
@RequestMapping("/edit")
public String edit(Clazz clazz){
this.clazzBiz.updateByPrimaryKeySelective(clazz);
return "redirect:/clz/list";
}
@RequestMapping("/del")
public String del(Clazz clazz){
this.clazzBiz.deleteByPrimaryKey(clazz.getCid());
return "redirect:/clz/list";
}
}
3.2.5新建一个aspect的包 在其中添加一个切面类
package com.hyx.springboot04.aspect;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hyx.springboot04.util.PageBean;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@Aspect
public class PagerAspect {
/**
* *:返回值类型
* *..:无限包
* *Service:以Service结尾接口名
* *Pager:以Pager方法
* 只要同时匹配上诉四个条件,就会被列为目标对象
* 上述配置要生效,代理注解<aop:aspectj-autoproxy/>不能少
* @param args
* @return
* @throws Throwable
*/
@Around("execution(* *..*Biz.*Pager(..))")
public Object invoke(ProceedingJoinPoint args) throws Throwable {
Object[] params = args.getArgs();
PageBean pageBean = null;
for (Object param : params) {
if(param instanceof PageBean){
pageBean = (PageBean)param;
break;
}
}
if(pageBean != null && pageBean.isPagination())
PageHelper.startPage(pageBean.getPage(),pageBean.getRows());
// 执行目标方法
Object list = args.proceed(params);
if(null != pageBean && pageBean.isPagination()){
PageInfo pageInfo = new PageInfo((List) list);
pageBean.setTotal(pageInfo.getTotal()+"");
}
return list;
}
}
3.2.6将jsp改为ftl
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link
href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css"
rel="stylesheet">
<script
src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.js"></script>
<title>博客列表</title>
<style type="text/css">
.page-item input {
padding: 0;
width: 40px;
height: 100%;
text-align: center;
margin: 0 6px;
}
.page-item input, .page-item b {
line-height: 38px;
float: left;
font-weight: 400;
}
.page-item.go-input {
margin: 0 10px;
}
</style>
<body>
<#--班级查询的搜索框-->
<#include '/common.ftl' >
<form class="form-inline"
action="${ctx }/templates/clz/list" method="post">
<div class="form-group mb-2">
<input type="text" class="form-control-plaintext" name="cname"
placeholder="请输入班级名称">
</div>
<button type="submit" class="btn btn-primary mb-2">查询</button>
<a class="btn btn-primary mb-2" href="${ctx }/templates/clz/toEdit">新增</a>
</form>
<table class="table table-striped bg-success">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">班级名称</th>
<th scope="col">指导老师</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
<#list lst as b>
<tr>
<td>${b.cid !}</td>
<td>${b.cname !}</td>
<td>${b.cteacher !}</td>
<td>
<a href="${ctx }/templates/clz/toEdit?cid=${b.cid}">修改</a>
<a href="${ctx }/templates/clz/del?cid=${b.cid}">删除</a>
</td>
</tr>
</#list>
</tbody>
</table>
</body>
</html>
测试运行
添加修改代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>博客的编辑界面</title>
</head>
<body>
<#include '/common.ftl'>
<#if b??>
<form action="${ctx }/clz/edit" method="post">
cid:<input type="text" name="cid" value="${b.cid }"><br>
cname:<input type="text" name="cname" value="${b.cname }"><br>
cteacher:<input type="text" name="cteacher" value="${b.cteacher }"><br>
<input type="submit">
</form>
<#else>
<form action="${ctx }/clz/add" method="post">
cid:<input type="text" name="cid" value=""><br>
cname:<input type="text" name="cname" value=""><br>
cteacher:<input type="text" name="cteacher" value=""><br>
<input type="submit">
</form>
</#if>
</body>
</html>