package db.model;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.Date;
@Getter
@Setter
@ToString
public class baseModel {
private Integer id;
private Date addTime;
private Date updateTime;
private Integer delTime;
public boolean isInsert() {
return id == null || id ==0;
}
public void prepareEdit(){
this.addTime =null;
this.updateTime =null;
this.delTime = null;
if (this.isInsert()){
this.id = null;
}
}
}
3.BootsTableRequest.java
package peanut.bean;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.apache.log4j.Logger;
import peanut.utils.PeanutUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;
@Getter
@Setter
@ToString
public class BootsTableRequest {
private static final Logger LOG = Logger.getLogger(BootsTableRequest.class);
private Integer limit; //限制每次查询获取到的数据条数
private Integer offset; //从第几条数据开始查询
private String order; //排序方式ASC DESC
private String search; //参与排序的字段
private String sort; //参与搜索的字段
private Map extras; //额外的请求参数
public void setLimit(Integer limit) {
this.limit = limit == null ? 1 : limit > 1 ? limit : 1; //限定最少查询一条数据
}
public void setOffset(Integer offset) {
this.offset = offset == null ? 0 : offset > 0 ? offset : 0;//限定最小值为0
}
public void setOrder(String order) {
this.order = "ASC".equalsIgnoreCase(order) ? "ASC" : "DESC";//排序方式只有两种
}
public void setSort(String sort) {
//参与排序的字段只允许出现数字 字母 下划线
this.sort = sort;
if (Pattern.matches("[0-9a-zA-Z_]+", sort)) {
this.sort = PeanutUtils.humpToLine(sort);
} else {
this.sort = null;
}
}
public void setSearch(String search) {
//只能输入数字 字母 下划线 中文字符
if (Pattern.matches("[0-9a-zA-Z_u4300-u9fa5]+", search)) {
//如果是模糊查询需要拼接%%
this.search = "%" + search + "%";
} else {
this.search = null;
}
}
public Integer getInteger(String key) {
return this.getExtra(key, Integer.class);
}
public String getString(String key) {
return this.getExtra(key, String.class);
}
public T getExtra(String key, Class targetClass) {
if (this.extras == null) return null;
Object value = this.extras.get(key);
if (value == null) return null;
if (Objects.equals(value.getClass(), targetClass)) {
return (T) value;
}
LOG.error(
String.format("数据类型转换失败,原始类型是:%s,目标数据类型是:%s,原始数据类型是: ",
value.getClass().getName(),
targetClass.getName())
+ value);
return null;
}
public void setExtra(String key, Object value) {
if (this.extras == null) this.extras = new HashMap<>();
this.extras.put(key, value);
}
}
4.UserRouterService.java接口
5.AbstractService
6. MasterController
package edu.td.peanut.controller;
import db.model.UserMaster;
import db.model.UserRouter;
import db.service.UserMasterService;
import db.service.UserRouterService;
import db.service.UserRuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import peanut.utils.PeanutUtils;
import javax.servlet.http.cookie;
import java.util.List;
@Controller
@RequestMapping(value = "master", method = RequestMethod.GET)
public class MasterController extends PublicController {
@Autowired
private UserRuleService ruleService;
@Autowired
private UserMasterService masterService;
@Autowired
private UserRouterService routerService;
@RequestMapping("login")
public String login() {
//删除用户登录状态,避免用户返回首页
session.removeAttribute("loginUser");
cookie cookie = new cookie("loginUser", null);
cookie.setMaxAge(0);//用于删除cookie
cookie.setHttpOnly(true);
cookie.setPath("/master");
response.addcookie(cookie);
//生成验证码和token
createCode();
createToken();
return "login";
}
@RequestMapping("login2")
public ModelAndView login2() {
ModelAndView modelAndView = new ModelAndView();
//指定需要加载的视图
modelAndView.setViewName("login2");
//生成验证码和token
createCode();
createToken();
return modelAndView;
}
@RequestMapping("lockScreen")
public String lockScreen() {
//删除用户登录状态,避免用户返回首页
session.removeAttribute("loginUser");
UserMaster master = (UserMaster) session.getAttribute("master");
if (master == null) {
master = masterService.findMasterByUsername(PeanutUtils.cookievalue(request, "loginUser"));
if (master == null) return "redirect:/master/login.do";
session.setAttribute("master", master);
}
return "lockScreen";
}
@RequestMapping("index")
public ModelAndView index(ModelAndView modelAndView) {
modelAndView.setViewName("index");
modelAndView.addObject("ruleList", ruleService.selectPageListByMaster((UserMaster) session.getAttribute("loginUser")));
return modelAndView;
}
@RequestMapping("userRule")
public String userRule() {
modelMap.addAttribute("ruleList", ruleService.selectAllParentList());
return "user/rule/list";
}
@RequestMapping("userRuleEdit")
public String userRuleEdit(Integer id) {
modelMap.addAttribute("editItem", ruleService.findByPrimaryKey(id));
modelMap.addAttribute("ruleList", ruleService.selectAllParentList());
return "user/rule/edit";
}
@RequestMapping("userMaster")
public String useMaster() {
UserMaster master = (UserMaster) session.getAttribute("loginUser");
//添加筛选项 - 角色筛选
List routerList = routerService.selectRouterList(master);
modelMap.addAttribute("routerList", routerList);
return "user/master/list";
}
@RequestMapping("userMasterEdit")
public String userMasterEdit(Integer id) {
UserMaster master = (UserMaster) session.getAttribute("loginUser");
//添加用户所属角色
List routerList = routerService.selectRouterList(master);
modelMap.addAttribute("routerList", routerList);
//写入id
modelMap.addAttribute("id", id);
//写入查询对象
modelMap.addAttribute("editItem", masterService.findByPrimaryKey(id));
return "user/master/edit";
}
}
7.MasterApiController
package edu.td.peanut.controller;
import db.model.UserMaster;
import db.model.UserRule;
import db.service.UserMasterService;
import db.service.UserRuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import peanut.bean.*;
import peanut.utils.PeanutUtils;
import java.util.Objects;
@Controller
@RequestMapping(value = "master", method = RequestMethod.POST)
public class MasterApiController extends PublicController {
@Autowired
private UserMasterService masterService;
@Autowired
private UserRuleService ruleService;
@Value("${system.defaultMasterPassword}")
private String defaultPassword;
@RequestMapping("loginDeal")
@ResponseBody//表示直接返回数据给请求对象(浏览器),无需加载指定界面
public ErrorBean loginDeal(@RequestBody LoginBean loginBean) {
if (loginBean == null) {
return ErrorBean.getInstance(1);
}
if (!checkCode(loginBean.getTdCode())) {
//验证码错误,请重试
return ErrorBean.getInstance(2);
}
UserMaster master = masterService.findMasterByUsername(loginBean.getTdUsername());
if (master == null) {
//用户名不存在,请重试
return ErrorBean.getInstance(101);
}
if (!Objects.equals(master.getMasterPassword(), PeanutUtils.md5(loginBean.getTdPassword()))) {
//登录密码错误,请重试
return ErrorBean.getInstance(102);
}
if (!checkToken(loginBean.getToken())) {
//token错误,当前请求非法
return ErrorBean.getInstance(3);
}
//先做其他数据验证,最终验证token
//记录登录对象
initMasterInfo(master);
//构造返回对象
return ErrorBean.getInstance(0)
.setTitle("登陆成功")
.setMsg("登陆成功,即将跳转首页")
.setUrl("/master/index.do");
}
@RequestMapping("loginDeal2")
public String loginDeal2(String tdUsername, String tdPassword, String tdCode, String token) {
if (!checkToken(token)) {
modelMap.addAttribute("url", "/master/login.do");
modelMap.addAttribute("msg", "token错误,当前请求非法");
return "error";
}
if (!checkCode(tdCode)) {
modelMap.addAttribute("url", "/master/login.do");
modelMap.addAttribute("msg", "验证码错误,请重试");
return "error";
}
if (!"admin".equals(tdUsername)) {
modelMap.addAttribute("url", "/master/login.do");
modelMap.addAttribute("msg", "用户名不存在,请重试");
return "error";
}
if (!"123456".equals(tdPassword)) {
modelMap.addAttribute("url", "/master/login.do");
modelMap.addAttribute("msg", "登录密码错误,请重试");
return "error";
}
//记录用户的登录状态
session.setAttribute("loginUser", "admin");
return "redirect:/master/index.do";
}
@RequestMapping("unlock")
public String unlock(String password) {
UserMaster master = (UserMaster) session.getAttribute("master");
if (master == null) {
master = masterService.findMasterByUsername(PeanutUtils.cookievalue(request, "loginUser"));
if (master == null) return "redirect:/master/login.do";
}
if (master.getMasterPassword().equals(PeanutUtils.md5(password))) {
//记录用户登录状态
initMasterInfo(master);
return "redirect:/master/index.do";
}
return "redirect:/master/lockScreen.do";
}
@RequestMapping("userRuleData")
@ResponseBody//表示直接返回数据给请求对象(浏览器),无需加载指定界面
public BootsTableResponse userRuleData(@RequestBody BootsTableRequest tableRequest) {
return ruleService.bootsData(tableRequest);
}
@RequestMapping("editUserRule")
@ResponseBody//表示直接返回数据给请求对象(浏览器),无需加载指定界面
public ErrorBean editUserRule(@RequestBody UserRule record) {
if (record == null) return ErrorBean.getInstance(1);
int lineCount = 0;//记录被影响的数据行数
if (record.getId() == null) {
//新增
lineCount = ruleService.insertSelective(record);
} else {
//修改
lineCount = ruleService.updateByPrimaryKey(record);
}
if (lineCount == 0) return ErrorBean.getInstance(4);
return ErrorBean.getInstance(0);
}
@RequestMapping("delUserRule")
@ResponseBody//表示直接返回数据给请求对象(浏览器),无需加载指定界面
public ErrorBean delUserRule(@RequestBody DeleteBean deleteBean) {
if (deleteBean == null || deleteBean.getIdList() == null) return ErrorBean.getInstance(1);
if (ruleService.delElementByIdList(deleteBean.getIdList()) == 0) return ErrorBean.getInstance(4);
return ErrorBean.getInstance(0);
}
@RequestMapping("userMasterData")
@ResponseBody
public BootsTableResponse userMasterData(@RequestBody BootsTableRequest tableRequest) {
UserMaster master = (UserMaster) session.getAttribute("loginUser");
//从Table的Extras参数内直接获取数据
Integer routerId = tableRequest.getExtra("routerId", Integer.class);
//超级管理员可以管理所有用户信息
if (master.getRouterId() > 1) {
if (routerId == null || routerId <= master.getRouterId()) {
routerId = master.getRouterId() + 1;
tableRequest.setExtra("routerId", routerId);
}
}
return masterService.bootsData(tableRequest);
}
@RequestMapping("editUserMaster")
@ResponseBody
public ErrorBean editUserMaster(@RequestBody UserMaster userMaster) {
if (userMaster == null) return ErrorBean.getInstance(1);
int resultLines = 0;//返回数据影响的行数
if (userMaster.isInsert()) {
userMaster.setMasterPassword(PeanutUtils.md5(defaultPassword));
resultLines = masterService.insertSelective(userMaster);
} else {
userMaster.setMasterPassword(null);
resultLines = masterService.updateByPrimaryKey(userMaster);
}
if (resultLines > 0) return ErrorBean.getInstance(0);
return ErrorBean.getInstance(4);
}
@RequestMapping("delUserMaster")
@ResponseBody
public ErrorBean delUserMaster(@RequestBody DeleteBean deleteBean) {
if (deleteBean == null) return ErrorBean.getInstance(1);
if (masterService.delElementByIdList(deleteBean.getIdList()) > 0) return ErrorBean.getInstance(0);
return ErrorBean.getInstance(5);
}
}
8.UserRuleServiceImpl
package edu.td.peanut.service;
import com.github.pagehelper.PageHelper;
import db.mapper.UserMasterRuleDynamicSqlSupport;
import db.mapper.UserRouterRuleDynamicSqlSupport;
import db.mapper.UserRuleMapper2;
import db.model.UserMaster;
import db.model.UserRule;
import db.model.UserRule2;
import db.service.AbstractService;
import db.service.UserRuleService;
import org.mybatis.dynamic.sql.select.join.EqualTo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import peanut.bean.BootsTableRequest;
import peanut.bean.BootsTableResponse;
import java.util.List;
import static org.mybatis.dynamic.sql.SqlBuilder.*;
import static db.mapper.UserRuleDynamicSqlSupport.*;
@Service
@Primary
public class UserRuleServiceImpl extends AbstractService implements UserRuleService {
@Autowired
private UserRuleMapper2 ruleMapper;
@Override
public UserRule findByPrimaryKey(Integer key) {
if (key == null || key < 1) return null;
return ruleMapper.selectByPrimaryKey(key).orElse(null);
}
@Override
public BootsTableResponse bootsData(BootsTableRequest tableRequest) {
if (tableRequest == null) return null;
//添加查询分页
PageHelper.offsetPage(tableRequest.getOffset(), tableRequest.getLimit());
return new BootsTableResponse<>(ruleMapper.select(entity -> {
//添加花括号是为了实现多行编码
entity.where(delTime, isEqualTo(0))
.and(
ruleName, isLikeWhenPresent(tableRequest.getSearch()),
or(ruleMethod, isLikeWhenPresent(tableRequest.getSearch())),
or(ruleType, isLikeWhenPresent(tableRequest.getSearch())),
or(ruleUrl, isLikeWhenPresent(tableRequest.getSearch()))
);
int _pid = (int) tableRequest.getExtras().get("pid");
if (_pid > 0) {
entity.where().and(pid, isEqualTo(_pid));
} else {
entity.where().and(pid, isNull());
}
//添加排序
super.sortByOrder(tableRequest, entity, userRule);
return entity;
}));
}
@Override
public int insertSelective(UserRule record) {
record.prepareEdit();
return ruleMapper.insertSelective(record);
}
@Override
public int updateByPrimaryKey(UserRule record) {
record.prepareEdit();
return ruleMapper.updateByPrimaryKeySelective(record);
}
@Override
public int delElementByIdList(List idList) {
if (idList == null || idList.isEmpty()) return 0;
return ruleMapper.update(entity -> entity
.set(delTime).equalTo((int) (System.currentTimeMillis() / 1000))
.where(id, isIn(idList))
);
}
@Override
public List selectAllParentList() {
return ruleMapper.select(entity -> entity
.where(delTime, isEqualTo(0))
.and(ruleType, isNotEqualTo("API"))
.and(ruleMethod, isEqualTo("GET"))
.orderBy(ruleType, ruleMethod, ruleName)
);
}
@Override
public boolean checkMasterRule(UserMaster master, String method, String uri) {
if (master == null) return false; //如果用户为空,则不给权限
if (master.getRouterId() == 1) return true;//超级管理员默认拥有所有权限
//初始化数据
final String _method = "GET".equalsIgnoreCase(method) ? "GET" : "POST";
final String _uri = uri.startsWith("/") ? uri : ("/" + uri);
//查询指定的权限是否已经定义
UserRule targetRule = ruleMapper.selectOne(entity -> entity
.where(delTime, isEqualTo(0))
.and(ruleMethod, isEqualTo(_method))
.and(ruleUrl, isEqualTo(_uri),
or(ruleUrl, isEqualTo(_uri.replaceFirst("/", "")))
)
).orElse(null);
if (targetRule == null) return true;//此时权限未在系统中定义,无需对当前权限做限制,,直接开启访问
//权限查两张表 masterRule routerRule 用于判断用户权限是否存在
return ruleMapper.selectOne(entity -> entity
.leftJoin(UserMasterRuleDynamicSqlSupport.userMasterRule).on(UserMasterRuleDynamicSqlSupport.ruleId, new EqualTo(id))
.leftJoin(UserRouterRuleDynamicSqlSupport.userRouterRule).on(UserRouterRuleDynamicSqlSupport.ruleId, new EqualTo(id))
.where(delTime, isEqualTo(0))
.and(
UserMasterRuleDynamicSqlSupport.delTime, isEqualTo(0),
or(UserMasterRuleDynamicSqlSupport.delTime, isNull())
)
.and(
UserRouterRuleDynamicSqlSupport.delTime, isEqualTo(0),
or(UserRouterRuleDynamicSqlSupport.delTime, isNull())
)
.and(
UserMasterRuleDynamicSqlSupport.ruleState, isEqualTo("GRANTED"),
or(
UserRouterRuleDynamicSqlSupport.ruleState, isEqualTo("GRANTED"),
and(
UserMasterRuleDynamicSqlSupport.id, isNull()
)
)
)
.and(UserMasterRuleDynamicSqlSupport.masterId, isEqualTo(master.getId()))
.and(UserRouterRuleDynamicSqlSupport.routerId, isEqualTo(master.getRouterId()))
.and(id, isEqualTo(targetRule.getId()))
).orElse(null) != null;
}
@Override
public List selectPageListByMaster(UserMaster master) {
if (master == null) return null;
if (master.getRouterId() == 1) {
return ruleMapper.select2(entity -> entity
.where(delTime, isEqualTo(0))
.and(ruleType, isEqualTo("NAV"))
.and(ruleMethod, isEqualTo("GET"))
.and(pid, isNull())
);
}
//TODO 查询管理员的页面导航列表
return null;
}
}
9.BootsTableRequest
package peanut.bean;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.apache.log4j.Logger;
import peanut.utils.PeanutUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;
@Getter
@Setter
@ToString
public class BootsTableRequest {
private static final Logger LOG = Logger.getLogger(BootsTableRequest.class);
private Integer limit; //限制每次查询获取到的数据条数
private Integer offset; //从第几条数据开始查询
private String order; //排序方式ASC DESC
private String search; //参与排序的字段
private String sort; //参与搜索的字段
private Map extras; //额外的请求参数
public void setLimit(Integer limit) {
this.limit = limit == null ? 1 : limit > 1 ? limit : 1; //限定最少查询一条数据
}
public void setOffset(Integer offset) {
this.offset = offset == null ? 0 : offset > 0 ? offset : 0;//限定最小值为0
}
public void setOrder(String order) {
this.order = "ASC".equalsIgnoreCase(order) ? "ASC" : "DESC";//排序方式只有两种
}
public void setSort(String sort) {
//参与排序的字段只允许出现数字 字母 下划线
this.sort = sort;
if (Pattern.matches("[0-9a-zA-Z_]+", sort)) {
this.sort = PeanutUtils.humpToLine(sort);
} else {
this.sort = null;
}
}
public void setSearch(String search) {
//只能输入数字 字母 下划线 中文字符
if (Pattern.matches("[0-9a-zA-Z_u4300-u9fa5]+", search)) {
//如果是模糊查询需要拼接%%
this.search = "%" + search + "%";
} else {
this.search = null;
}
}
public Integer getInteger(String key) {
return this.getExtra(key, Integer.class);
}
public String getString(String key) {
return this.getExtra(key, String.class);
}
public T getExtra(String key, Class targetClass) {
if (this.extras == null) return null;
Object value = this.extras.get(key);
if (value == null) return null;
if (Objects.equals(value.getClass(), targetClass)) {
return (T) value;
}
LOG.error(
String.format("数据类型转换失败,原始类型是:%s,目标数据类型是:%s,原始数据类型是: ",
value.getClass().getName(),
targetClass.getName())
+ value);
return null;
}
public void setExtra(String key, Object value) {
if (this.extras == null) this.extras = new HashMap<>();
this.extras.put(key, value);
}
}
10.UserRouterServiceImpl
package edu.td.peanut.service;
import db.mapper.UserRouterMapper;
import db.model.UserMaster;
import db.model.UserRouter;
import db.service.AbstractService;
import db.service.UserRouterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import peanut.bean.BootsTableRequest;
import peanut.bean.BootsTableResponse;
import java.util.List;
import static org.mybatis.dynamic.sql.SqlBuilder.*;
import static db.mapper.UserRouterDynamicSqlSupport.*;
@Service
@Primary
public class UserRouterServiceImpl extends AbstractService implements UserRouterService {
@Autowired
private UserRouterMapper routerMapper;
@Override
public UserRouter findByPrimaryKey(Integer key) {
return null;
}
@Override
public BootsTableResponse bootsData(BootsTableRequest tableRequest) {
return null;
}
@Override
public int insertSelective(UserRouter record) {
return 0;
}
@Override
public int updateByPrimaryKey(UserRouter record) {
return 0;
}
@Override
public int delElementByIdList(List idList) {
return 0;
}
@Override
public List selectRouterList(UserMaster master) {
if (master==null) return null;
return routerMapper.select(entity->{
entity.where(delTime,isEqualTo(0));
if (master.getRouterId()>1){
entity.where().and(id,isGreaterThan(master.getRouterId()));
}
entity.orderBy(addTime.descending());
return entity;
});
}
}
11.UserMasterServiceImpl
package edu.td.peanut.service;
import com.github.pagehelper.PageHelper;
import db.mapper.UserMasterMapper;
import db.model.UserMaster;
import db.service.AbstractService;
import db.service.UserMasterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import peanut.bean.BootsTableRequest;
import peanut.bean.BootsTableResponse;
import java.util.List;
import static org.mybatis.dynamic.sql.SqlBuilder.*;
import static db.mapper.UserMasterDynamicSqlSupport.*;
@Service//声明当前类是用于数据查询的服务类
@Primary//当实现接口MasterService有多个实现类的时候,@Primary用于声明当前类是默认实现类,同一个接口的众多实现类中只有一个实现类可以添加@Primary注解
public class UserMasterServiceImpl extends AbstractService implements UserMasterService {
@Autowired
private UserMasterMapper masterMapper;//初始化查询接口
@Override
public UserMaster findByPrimaryKey(Integer key) {
if (key == null || key < 1) return null;
return masterMapper.selectByPrimaryKey(key).orElse(null);
}
@Override
public BootsTableResponse bootsData(BootsTableRequest tableRequest) {
if (tableRequest == null) return null;
//数据分页
PageHelper.offsetPage(tableRequest.getOffset(), tableRequest.getLimit());
//数据查询
return new BootsTableResponse<>(masterMapper.select(entity -> {
entity.where(delTime, isEqualTo(0))
.and(masterName, isLikeWhenPresent(tableRequest.getSearch()))
.and(routerId, isEqualToWhenPresent(tableRequest.getInteger("routerId")));
//添加排序
super.sortByOrder(tableRequest,entity,userMaster);
return entity;
}));
}
@Override
public int insertSelective(UserMaster record) {
if (record == null) return 0;
record.prepareEdit();
record.setId(null);
return masterMapper.insertSelective(record);
}
@Override
public int updateByPrimaryKey(UserMaster record) {
if (record == null) return 0;
record.prepareEdit();
return masterMapper.updateByPrimaryKeySelective(record);
}
@Override
public int delElementByIdList(List idList) {
if (idList == null || idList.isEmpty()) return 0;
return masterMapper.update(entity -> entity
.set(delTime).equalTo((int) (System.currentTimeMillis() / 1000))
);
}
@Override
public UserMaster findMasterByUsername(String userName) {
if (StringUtils.isEmpty(userName)) return null;
return masterMapper.selectOne(entity -> entity
.where(delTime, isEqualTo(0))
.and(masterUsername, isEqualTo(userName))
).orElse(null);
}
}
12.user下新建master文件夹,new edit.jsp list.jsp
master-edit.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ include file="/WEB-INF/layout/header.jsp" %><%@include file="/WEB-INF/layout/footer.jsp" %>


