package com.controller; import java.io.File; import java.math.BigDecimal; import java.net.URL; import java.text.SimpleDateFormat; import com.alibaba.fastjson.JSONObject; import java.util.*; import org.springframework.beans.BeanUtils; import javax.servlet.http.HttpServletRequest; import org.springframework.web.context.ContextLoader; import javax.servlet.ServletContext; import com.service.TokenService; import com.utils.*; import java.lang.reflect.InvocationTargetException; import com.service.DictionaryService; import org.apache.commons.lang3.StringUtils; import com.annotation.IgnoreAuth; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.mapper.Wrapper; import com.entity.*; import com.entity.view.*; import com.service.*; import com.utils.PageUtils; import com.utils.R; import com.alibaba.fastjson.*; /** * 论坛 * 后端接口 * 该类主要作为论坛相关功能的控制层,处理各种与论坛业务相关的HTTP请求,调用对应的服务层方法来实现具体功能, * 并与数据库进行交互以及处理返回结果等操作。 * @author WMZ * @email */ @RestController @Controller @RequestMapping("/forum") public class ForumController { // 创建日志记录器, // 用于记录该类中各个方法执行过程中的关键信息,方便调试和问题排查 private static final Logger logger = LoggerFactory.getLogger(ForumController.class); // 通过Spring的依赖注入,自动装配ForumService, // 用于处理论坛相关的业务逻辑,比如查询、插入、更新、删除等操作 @Autowired private ForumService forumService; // 自动注入TokenService, // 可能用于处理用户认证相关的令牌操作(具体功能需看对应服务层实现) @Autowired private TokenService tokenService; // 自动注入DictionaryService, // 用于处理字典表相关的数据转换等操作(比如将字典表中的编码转换为对应的有意义的值等) @Autowired private DictionaryService dictionaryService; // 自动注入YonghuService, // 用于处理与用户(Yonghu,可能是具体业务中的一种用户类型)相关的级联表操作 @Autowired private YonghuService yonghuService; // 自动注入UsersService, // 用于处理与普通用户相关的级联表操作(比如获取用户详细信息等) @Autowired private UsersService usersService; /** * 后端列表功能方法 * 接收前端传来的查询参数params以及HttpServletRequest对象,用于获取分页数据以及进行相关业务逻辑处理, * 根据参数查询论坛信息列表,并进行字典表数据转换后返回给前端。 * @param params 包含查询条件、分页等相关参数的Map集合 * @param request HttpServletRequest对象,用于获取请求相关的信息(如会话中的属性等) * @return R类型的结果对象,包含操作结果状态以及查询到的数据等信息(R应该是自定义的统一返回结果类型) */ @RequestMapping("/page") public R page(@RequestParam Map params, HttpServletRequest request) { // 记录page方法的调用信息, // 包括当前类名和传入的参数, // 方便调试查看参数情况(以JSON字符串形式记录参数) logger.debug("page方法:,,Controller:{},,params:{}", this.getClass().getName(), JSONObject.toJSONString(params)); // 如果传入的排序字段参数为空, // 则默认按照"id"字段进行排序 if (params.get("orderBy") == null || params.get("orderBy") == "") { params.put("orderBy", "id"); } // 调用forumService的queryPage方法, // 根据传入的参数获取分页数据(该方法内部应该是与数据库交互获取相应的数据列表等) PageUtils page = forumService.queryPage(params); // 获取分页数据中的列表数据 // (这里应该是ForumView类型的列表,ForumView可能是用于展示的视图对象) List list = (List) page.getList(); // 遍历列表数据, // 对每条数据进行字典表数据转换操作(比如将字典表中的编码转换为对应的实际含义显示给前端) for (ForumView c : list) { dictionaryService.dictionaryConvert(c, request); } // 返回包含处理后数据的成功结果对象 // (R.ok()表示操作成功,并将数据放入返回对象中返回给前端) return R.ok().put("data", page); } /** * 后端详情功能方法 * 根据传入的论坛记录id,从数据库中查询对应的论坛详细信息, * 进行相关的实体转视图、级联表数据处理以及字典表数据转换后返回给前端。 * @param id 要查询的论坛记录的唯一标识(Long类型的id) * @param request HttpServletRequest对象, * 用于获取请求相关的信息(如会话中的属性等) * @return R类型的结果对象, * 包含操作结果状态以及查询到的详细数据等信息(若查询到数据则返回成功及数据,否则返回错误提示) */ @RequestMapping("/info/{id}") public R info(@PathVariable("id") Long id, HttpServletRequest request) { logger.debug("info方法:,,Controller:{},,id:{}", this.getClass().getName(), id); // 通过forumService根据传入的id从数据库中查询对应的ForumEntity对象(ForumEntity可能是数据库对应的实体类) ForumEntity forum = forumService.selectById(id); if (forum!= null) { // 创建ForumView对象, // 用于将查询到的实体数据转换为适合展示的视图数据(ForumView可能包含了部分需要展示给前端的字段等) ForumView view = new ForumView(); // 使用Spring的BeanUtils工具, // 将forum实体对象中的属性值复制到view视图对象中 BeanUtils.copyProperties(forum, view); // 处理级联表数据, // 获取与该论坛记录关联的YonghuEntity(用户相关的实体对象),并将部分属性复制到view中(排除一些不需要的字段) YonghuEntity yonghu = yonghuService.selectById(forum.getYonghuId()); if (yonghu!= null) { BeanUtils.copyProperties(yonghu, view, new String[] { "id", "createTime", "insertTime", "updateTime" }); view.setYonghuId(yonghu.getId()); } // 处理管理员用户表数据, // 获取与该论坛记录关联的UsersEntity(管理员用户相关的实体对象),并将部分关键属性设置到view中 UsersEntity users = usersService.selectById(forum.getUsersId()); if (users!= null) { view.setUsersId(users.getId()); view.setUusername(users.getUsername()); view.setUpassword(users.getPassword()); view.setUrole(users.getRole()); view.setUaddtime(users.getAddtime()); } // 对view视图对象进行字典表数据转换操作 // (比如将字典表中的编码转换为对应的实际含义显示给前端) dictionaryService.dictionaryConvert(view, request); // 返回包含处理后详细数据的成功结果对象(R.ok()表示操作成功, // 并将数据放入返回对象中返回给前端) return R.ok().put("data", view); } else { // 如果未查询到对应的数据, // 则返回包含错误码和错误提示信息的错误结果对象 return R.error(511, "查不到数据"); } } /** * 后端保存功能方法 * 接收前端传来的ForumEntity对象(包含要保存的论坛相关数据)以及HttpServletRequest对象, * 根据当前用户角色设置相关的关联用户id,并检查数据是否重复后将数据插入到数据库中。 * @param forum 包含要保存的论坛相关数据的ForumEntity对象 * @param request HttpServletRequest对象,用于获取请求相关的信息(如会话中的用户角色、用户id等属性) * @return R类型的结果对象,包含操作结果状态(成功或失败及对应的提示信息) */ @RequestMapping("/save") public R save(@RequestBody ForumEntity forum, HttpServletRequest request) { logger.debug("save方法:,,Controller:{},,forum:{}", this.getClass().getName(), forum.toString()); // 从HttpServletRequest的会话中获取当前用户的角色信息(这里先将获取到的Object类型强制转换为String类型) String role = String.valueOf(request.getSession().getAttribute("role")); if (false) return R.error(511, "永远不会进入"); else if ("用户".equals(role)) // 如果当前用户角色是"用户", // 则将论坛记录的YonghuId设置为从会话中获取的当前用户的id(这里做了一些类型转换操作) forum.setYonghuId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); else if ("管理员".equals(role)) // 如果当前用户角色是"管理员", // 则将论坛记录的UsersId设置为从会话中获取的当前用户的id(同样进行了类型转换) forum.setUsersId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); // 创建EntityWrapper对象, // 用于构建查询条件,检查数据库中是否已经存在相同的数据(根据多个字段进行等值判断) Wrapper queryWrapper = new EntityWrapper() .eq("forum_name", forum.getForumName()) .eq("yonghu_id", forum.getYonghuId()) .eq("users_id", forum.getUsersId()) .eq("super_ids", forum.getSuperIds()) .eq("forum_state_types", forum.getForumStateTypes()); logger.info("sql语句:" + queryWrapper.getSqlSegment()); // 根据构建的查询条件查询数据库中是否已经存在相同的数据 // (通过selectOne方法查询一条符合条件的数据) ForumEntity forumEntity = forumService.selectOne(queryWrapper); if (forumEntity == null) { // 如果不存在相同数据, // 则设置论坛记录的插入时间和创建时间为当前时间,并将该记录插入到数据库中(通过insert方法) forum.setInsertTime(new Date()); forum.setCreateTime(new Date()); forumService.insert(forum); return R.ok(); } else { // 如果存在相同数据, // 则返回包含错误码和提示信息的错误结果对象,表示表中已有相同数据 return R.error(511, "表中有相同数据"); } } /** * 后端修改功能方法 * 接收前端传来的ForumEntity对象(包含要修改的论坛相关数据)以及HttpServletRequest对象, * 根据字段查询是否有相同数据,若不存在则根据id更新数据库中的对应论坛记录。 * @param forum 包含要修改的论坛相关数据的ForumEntity对象 * @param request HttpServletRequest对象,用于获取请求相关的信息(如会话中的用户角色等属性) * @return R类型的结果对象,包含操作结果状态(成功或失败及对应的提示信息) */ @RequestMapping("/update") public R update(@RequestBody ForumEntity forum, HttpServletRequest request) { logger.debug("update方法:,,Controller:{},,forum:{}", this.getClass().getName(), forum.toString()); String role = String.valueOf(request.getSession().getAttribute("role")); // if (false) // return R.error(511, "永远不会进入"); // else if ("用户".equals(role)) // forum.setYonghuId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); // else if ("管理员".equals(role)) // forum.setUsersId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); // 创建EntityWrapper对象,用于构建查询条件,检查数据库中除了当前要修改的记录(根据id排除)外是否存在相同的数据(根据多个字段进行等值判断) Wrapper queryWrapper = new EntityWrapper() .notIn("id", forum.getId()) .andNew() .eq("forum_name", forum.getForumName()) .eq("yonghu_id", forum.getYonghuId()) .eq("users_id", forum.getUsersId()) .eq("super_ids", forum.getSuperIds()) .eq("forum_state_types", forum.getForumStateTypes()); logger.info("sql语句:" + queryWrapper.getSqlSegment()); // 根据构建的查询条件查询数据库中是否已经存在相同的数据(通过selectOne方法查询一条符合条件的数据) ForumEntity forumEntity = forumService.selectOne(queryWrapper); // 设置论坛记录的更新时间为当前时间 forum.setUpdateTime(new Date()); if (forumEntity == null) { // 如果不存在相同数据, // 则根据传入的forum对象的id更新数据库中的对应论坛记录(通过updateById方法) forumService.updateById(forum); return R.ok(); } else { // 如果存在相同数据, // 则返回包含错误码和提示信息的错误结果对象,表示表中已有相同数据 return R.error(511, "表中有相同数据"); } } /** * 删除功能方法 * 接收前端传来的要删除的论坛记录的id数组,调用forumService的批量删除方法,从数据库中删除对应的数据记录, * 并返回操作结果给前端。 * @param ids 包含要删除的论坛记录的id的整数数组 * @return R类型的结果对象,包含操作结果状态(成功或失败及对应的提示信息) */ @RequestMapping("/delete") public R delete(@RequestBody Integer[] ids) { logger.debug("delete:,,Controller:{},,ids:{}", this.getClass().getName(), ids.toString()); // 调用forumService的deleteBatchIds方法, // 批量删除数据库中对应id的论坛记录(传入的是将数组转换为List后的集合) forumService.deleteBatchIds(Arrays.asList(ids)); return R.ok(); } /** * 批量上传功能方法 * 接收文件名fileName以及HttpServletRequest对象,用于将指定的Excel文件中的论坛数据批量插入到数据库中, * 在插入前进行一些文件格式校验、数据读取以及重复数据检查等操作。 * @param fileName 要上传的文件的名称(这里应该是位于特定目录下的文件名) * @param request HttpServletRequest对象,用于获取请求相关的信息(如当前用户的id等属性) * @return R类型的结果对象,包含操作结果状态(成功或失败及对应的提示信息) */ @RequestMapping("/batchInsert") public R save(String fileName, HttpServletRequest request) { logger.debug("batchInsert方法:,,Controller:{},,fileName:{}", this.getClass().getName(), fileName); // 从HttpServletRequest的会话中获取当前用户的id,并转换为Integer类型(这里做了一些强制类型转换操作) Integer yonghuId = Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { // 创建一个用于存储要插入数据库的ForumEntity对象列表(即从文件中读取到的多条论坛数据记录) List forumList = new ArrayList<>(); // 创建一个Map,用于存储要查询是否重复的字段信息(具体的使用方式需看后续代码逻辑) Map> seachFields = new HashMap<>(); Date date = new Date(); int lastIndexOf = fileName.lastIndexOf("."); if (lastIndexOf == -1) { return R.error(511, "该文件没有后缀"); } else { String suffix = fileName.substring(lastIndexOf); if (!".xls".equals(suffix)) { return R.error(511, "只支持后缀为xls的excel文件"); } else { // 通过类加载器获取指定文件名对应的文件资源路径(这里应该是位于"static/upload/"目录下的文件) URL resource = this.getClass().getClassLoader().getResource("static/upload/" + fileName); File file = new File(resource.getFile()); if (!file.exists()) { return R.error(511, "找不到上传文件,请联系管理员"); } else { // 调用PoiUtil的poiImport方法读取Excel文件中的数据(返回的是一个嵌套的List,外层List表示行,内层List表示每行中的单元格数据) List> dataList = PoiUtil.poiImport(file.getPath()); // 删除读取到的数据列表中的第一行(可能是表头之类的提示信息,不需要插入数据库) dataList.remove(0); for (List data : dataList) { // 循环处理每一行数据,创建一个ForumEntity对象,用于存储要插入数据库的一条论坛记录信息 ForumEntity forumEntity = new ForumEntity(); // forumEntity.setForumName(data.get(0)); //帖子标题 要改的 // forumEntity.setYonghuId(Integer.valueOf(data.get(0))); //用户 要改的 // forumEntity.setUsersId(Integer.valueOf(data.get(0))); //管理员 要改的 // forumEntity.setForumContent("");//详情和图片 // forumEntity.setSuperIds(Integer.valueOf(data.get(0))); //父id 要改的 // forumEntity.setForumStateTypes(Integer.valueOf(data.get(0))); //帖子状态 要改的