初出茅庐.开胃菜·代码思路· 4-1-看代码(实现)
初出茅庐.开胃菜·代码思路· 4-1-看代码(实现)
1.看什么?哪些是重点?哪些是非重点?如何区分
代码层面
1.1返回的对象的封装类是什么
系统提供了
AjaxResult和TableDataInfo两个封装类
其中AjaxResult主要是用来封装一些非分页对象的
AjaxResult具有三个属性:code msg data
其中提供了很多方法用来描述接口调用成功还是失败
package com.huike.common.core.domain;
import java.util.HashMap;
import com.huike.common.constant.HttpStatus;
import com.huike.common.utils.StringUtils;
/**
* 操作消息提醒
*
*
*/
public class AjaxResult extends HashMap<String, Object>
{
private static final long serialVersionUID = 1L;
/** 状态码 */
public static final String CODE_TAG = "code";
/** 返回内容 */
public static final String MSG_TAG = "msg";
/** 数据对象 */
public static final String DATA_TAG = "data";
/**
* 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
*/
public AjaxResult()
{
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
* @param code 状态码
* @param msg 返回内容
*/
public AjaxResult(int code, String msg)
{
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
* @param code 状态码
* @param msg 返回内容
* @param data 数据对象
*/
public AjaxResult(int code, String msg, Object data)
{
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
if (StringUtils.isNotNull(data))
{
super.put(DATA_TAG, data);
}
}
/**
* 返回成功消息
*
* @return 成功消息
*/
public static AjaxResult success()
{
return AjaxResult.success("操作成功");
}
/**
* 返回成功数据
*
* @return 成功消息
*/
public static AjaxResult success(Object data)
{
return AjaxResult.success("操作成功", data);
}
/**
* 返回成功消息
*
* @param msg 返回内容
* @return 成功消息
*/
public static AjaxResult success(String msg)
{
return AjaxResult.success(msg, null);
}
/**
* 返回成功消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 成功消息
*/
public static AjaxResult success(String msg, Object data)
{
return new AjaxResult(HttpStatus.SUCCESS, msg, data);
}
/**
* 返回错误消息
*
* @return
*/
public static AjaxResult error()
{
return AjaxResult.error("操作失败");
}
/**
* 返回错误消息
*
* @param msg 返回内容
* @return 警告消息
*/
public static AjaxResult error(String msg)
{
return AjaxResult.error(msg, null);
}
/**
* 返回错误消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/
public static AjaxResult error(String msg, Object data)
{
return new AjaxResult(HttpStatus.ERROR, msg, data);
}
/**
* 返回错误消息
*
* @param code 状态码
* @param msg 返回内容
* @return 警告消息
*/
public static AjaxResult error(int code, String msg)
{
return new AjaxResult(code, msg, null);
}
}
其中TableDataInfo主要是用来返回分页的数据的
TableDataInfo包含了total 总条数 rows列表数据 code 状态码 msg消息内容 params(其他参数)
package com.huike.common.core.page;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* 表格分页数据对象
*
*
*/
public class TableDataInfo implements Serializable{
private static final long serialVersionUID = 1L;
/** 总记录数 */
private long total;
/** 列表数据 */
private List<?> rows;
/** 消息状态码 */
private int code;
/** 消息内容 */
private String msg;
private Map<String,Object> params;
/**
* 表格数据对象
*/
public TableDataInfo()
{
}
/**
* 分页
*
* @param list 列表数据
* @param total 总记录数
*/
public TableDataInfo(List<?> list, int total)
{
this.rows = list;
this.total = total;
}
public Map<String, Object> getParams() {
return params;
}
public void setParams(Map<String, Object> params) {
this.params = params;
}
public long getTotal()
{
return total;
}
public void setTotal(long total)
{
this.total = total;
}
public List<?> getRows()
{
return rows;
}
public void setRows(List<?> rows)
{
this.rows = rows;
}
public int getCode()
{
return code;
}
public void setCode(int code)
{
this.code = code;
}
public String getMsg()
{
return msg;
}
public void setMsg(String msg)
{
this.msg = msg;
}
}
代码中使用的时候将所有分页的方法都写在了BaseController中,在BaseController中有很多获取TableDataInfo的方法
package com.huike.common.core.controller;
import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.huike.common.constant.HttpStatus;
import com.huike.common.core.domain.AjaxResult;
import com.huike.common.core.page.PageDomain;
import com.huike.common.core.page.TableDataInfo;
import com.huike.common.core.page.TableSupport;
import com.huike.common.utils.DateUtils;
import com.huike.common.utils.StringUtils;
import com.huike.common.utils.sql.SqlUtil;
/**
* web层通用数据处理
*
*
*/
public class BaseController
{
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 将前台传递过来的日期格式的字符串,自动转化为Date类型
*/
@InitBinder
public void initBinder(WebDataBinder binder)
{
// Date 类型转换
binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
{
@Override
public void setAsText(String text)
{
setValue(DateUtils.parseDate(text));
}
});
}
/**
* 设置请求分页数据
*/
protected void startPage()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.startPage(pageNum, pageSize, orderBy);
}
}
/**
* 响应请求分页数据
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected TableDataInfo getDataTable(List<?> list){
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功");
rspData.setRows(list);
rspData.setTotal(new PageInfo(list).getTotal());
return rspData;
}
/**
* 手工分页
* @param list
* @return
*/
public TableDataInfo getDataTablePage(List<?> list) {
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功");
int total = list.size();
if (total > pageSize) {
int toIndex = pageSize * pageNum;
if (toIndex > total) {
toIndex = total;
}
list = list.subList(pageSize * (pageNum - 1), toIndex);
}
rspData.setRows(list);
rspData.setTotal(total);
return rspData;
}
protected TableDataInfo getDataTable(List<?> list, Map<String,Object> params)
{
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功");
rspData.setRows(list);
rspData.setTotal(new PageInfo(list).getTotal());
rspData.setParams(params);
return rspData;
}
protected TableDataInfo getDataTablePage(List<?> list, Map<String,Object> params)
{
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功");
int total = list.size();
if (total > pageSize) {
int toIndex = pageSize * pageNum;
if (toIndex > total) {
toIndex = total;
}
list = list.subList(pageSize * (pageNum - 1), toIndex);
}
rspData.setRows(list);
rspData.setTotal(total);
rspData.setParams(params);
return rspData;
}
/**
* 响应返回结果
*
* @param rows 影响行数
* @return 操作结果
*/
protected AjaxResult toAjax(int rows)
{
return rows > 0 ? AjaxResult.success() : AjaxResult.error();
}
/**
* 响应返回结果
*
* @param result 结果
* @return 操作结果
*/
protected AjaxResult toAjax(boolean result)
{
return result ? success() : error();
}
/**
* 返回成功
*/
public AjaxResult success()
{
return AjaxResult.success();
}
/**
* 返回失败消息
*/
public AjaxResult error()
{
return AjaxResult.error();
}
/**
* 返回成功消息
*/
public AjaxResult success(String message)
{
return AjaxResult.success(message);
}
/**
* 返回失败消息
*/
public AjaxResult error(String message)
{
return AjaxResult.error(message);
}
/**
* 页面跳转
*/
public String redirect(String url)
{
return StringUtils.format("redirect:{}", url);
}
}
1.3三层架构是如何编写的
controller层 主要写在admin工程中的controller包下
service层主要写在各个业务工程的service包下 service目录下是接口 impl包下是具体的实现类
mapper层主要写在各个业务工程下的mapper目录下 mapper目录下是接口
对应的xml文件是在各个模块的resource目录下有具体的xml文件
xml与mapper接口的对应是写在xml文件中对应了mapper接口的全路径
如图所示:
1.4业务中数据的状态有哪些,是写在哪里的
线索状态写在了线索的实体类中的一个枚举类中
public enum StatusType{
UNFOLLOWED("待跟进","1"),
FOLLOWING("跟进中","2"),
RECOVERY("回收","3"),
FALSE("伪线索/踢回公海","4"),
DELETED("删除","5"),
TOBUSINESS("转换商机","6"),
TOCUSTOMER("转换客户","7");
private String name;
private String value;
private StatusType(String name,String value)
{
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
}
商机集成了线索,状态与线索的状态相同
public class TbBusiness extends TbClue{
1.5数据库层面
**
1.6项目结构层面
各个模块对应的职责是什么
admin工程主要提供的是程序的入口即controller和springboot的启动类
其他的工程主要是对应功能模块的业务层和数据持久层和一些对应模块的封装类,工具类等等
如商机和线索模块
2.统一的全局异常处理
参考实现锦囊里的demo了解@RestControllerAdvice
在huike-framework模块下有一个web目录,下面定义了一个全局异常处理的处理器

在这个全局异常处理类里我们处理了一些我们自定义的自定义异常
package com.huike.framework.web.exception;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import com.huike.common.constant.HttpStatus;
import com.huike.common.core.domain.AjaxResult;
import com.huike.common.exception.BaseException;
import com.huike.common.exception.CustomException;
import com.huike.common.utils.StringUtils;
/**
* 全局异常处理器
* @author wgl
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 基础异常
*/
@ExceptionHandler(BaseException.class)
public AjaxResult baseException(BaseException e)
{
return AjaxResult.error(e.getMessage());
}
/**
* 业务异常
*/
@ExceptionHandler(CustomException.class)
public AjaxResult businessException(CustomException e)
{
if (StringUtils.isNull(e.getCode()))
{
return AjaxResult.error(e.getMessage());
}
return AjaxResult.error(e.getCode(), e.getMessage());
}
@ExceptionHandler(NoHandlerFoundException.class)
public AjaxResult handlerNoFoundException(Exception e)
{
log.error(e.getMessage(), e);
return AjaxResult.error(HttpStatus.NOT_FOUND, "路径不存在,请检查路径是否正确");
}
@ExceptionHandler(AccessDeniedException.class)
public AjaxResult handleAuthorizationException(AccessDeniedException e)
{
log.error(e.getMessage());
return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权");
}
@ExceptionHandler(AccountExpiredException.class)
public AjaxResult handleAccountExpiredException(AccountExpiredException e)
{
log.error(e.getMessage(), e);
return AjaxResult.error(e.getMessage());
}
@ExceptionHandler(UsernameNotFoundException.class)
public AjaxResult handleUsernameNotFoundException(UsernameNotFoundException e)
{
log.error(e.getMessage(), e);
return AjaxResult.error(e.getMessage());
}
@ExceptionHandler(Exception.class)
public AjaxResult handleException(Exception e)
{
log.error(e.getMessage(), e);
return AjaxResult.error(e.getMessage());
}
/**
* 自定义验证异常
*/
@ExceptionHandler(BindException.class)
public AjaxResult validatedBindException(BindException e)
{
log.error(e.getMessage(), e);
String message = e.getAllErrors().get(0).getDefaultMessage();
return AjaxResult.error(message);
}
/**
* 自定义验证异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Object validExceptionHandler(MethodArgumentNotValidException e) {
log.error(e.getMessage(), e);
String message = e.getBindingResult().getFieldError().getDefaultMessage();
return AjaxResult.error(message);
}
}
3.基于现有的三层架构编写一个最简单的CRUD
3.1controller
package com.huike.web.controller.review;
import com.huike.clues.domain.TbClue;
import com.huike.common.core.controller.BaseController;
import com.huike.common.core.domain.AjaxResult;
import com.huike.common.core.page.TableDataInfo;
import com.huike.review.pojo.Review;
import com.huike.review.service.ReviewService;
import com.huike.review.vo.MybatisReviewVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 该Controller主要是为了复习三层架构以及Mybatis使用的,该部分接口已经放开权限,可以直接访问
* 同学们在此处编写接口通过浏览器访问看是否能完成最简单的增删改查
*/
@RestController
@RequestMapping("/review")
public class MybatisReviewController extends BaseController {
@Autowired
private ReviewService reviewService;
/**=========================================================新增数据============================================*/
/**
* 保存数据的方法
* 同学需要将对应的方法补全,用于检验同学对三层架构的熟悉程度
* 判断学员能否独立编写接口
* @param name 姓名
* @param age 年龄
* @param name 性别(传入男,女)
* @return
*/
@GetMapping("/saveData/{name}/{age}/{sex}")
public AjaxResult saveData(@PathVariable("name") String name,
@PathVariable("age") String age,
@PathVariable("sex")String sex){
return AjaxResult.success(reviewService.saveData(name,age,sex));
}
/**
* 保存数据的方法
* 同学需要将对应的方法补全,用于检验同学对三层架构的熟悉程度
* 判断学员能否独立编写接口
* 注:
* @param reviewVO 用户对象
* @return
*/
@PostMapping("/saveData")
public AjaxResult saveData(@RequestBody MybatisReviewVO reviewVO){
return AjaxResult.success(reviewService.saveData(reviewVO));
}
/**=========================================================删除数据=============================================*/
/**
* 删除数据的方法
* @param id 传入主键id
* @return
*/
@DeleteMapping("/remove/{id}")
public AjaxResult removeId(@PathVariable("id")Long id){
return AjaxResult.success(reviewService.removeData(id));
}
/**=========================================================修改数据=============================================*/
@PostMapping("/update")
public AjaxResult update(@RequestBody MybatisReviewVO reviewVO){
return AjaxResult.success(reviewService.updateData(reviewVO));
}
/**=========================================================查询数据=============================================*/
/**
* 根据id查询对应数据的方法
* 同学需要将对应的方法补全,用于检验同学对三层架构的熟悉程度
* 判断学员能否独立编写接口
* @param id
* @return
*/
@GetMapping("/getById")
public AjaxResult getDataById(@RequestParam("id") Long id){
return AjaxResult.success(reviewService.getDataById(id));
}
/**
* 分页查询数据的方法
* @return
*/
@GetMapping("/getDataByPage")
public TableDataInfo getDataByPage(){
startPage();
List<Review> list = reviewService.getDataByPage();
return getDataTable(list);
}
}
3.2service
package com.huike.review.service;
import com.huike.review.pojo.Review;
import com.huike.review.vo.MybatisReviewVO;
import java.util.List;
/**
* mybatis复习接口层
*/
public interface ReviewService {
/**
* 根据id获取数据的方法
* @param id
* @return
*/
public Review getDataById(Long id);
/**
* 根据传入的参数保存数据的方法
* @param name
* @param age
* @param sex
* @return
*/
String saveData(String name, String age, String sex);
/**
* 方法重载:方法名相同 传递参数不同
* @param user 前端传入对象
* @return
*/
String saveData(MybatisReviewVO user);
/**
* 删除数据的方法
* @param id
* @return
*/
String removeData(Long id);
/**
* 修改数据的方法
* @param reviewVO
* @return
*/
String updateData(MybatisReviewVO reviewVO);
/**
* 分页查询对应数据的方法
* @return
*/
List<Review> getDataByPage();
}
3.3serviceimpl
package com.huike.review.service.impl;
import com.huike.common.core.domain.AjaxResult;
import com.huike.common.exception.CustomException;
import com.huike.common.utils.bean.BeanUtils;
import com.huike.review.pojo.Review;
import com.huike.review.service.ReviewService;
import com.huike.review.mapper.MybatisReviewMapper;
import com.huike.review.vo.MybatisReviewVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* mybatis复习使用的业务层
* 注意该业务层和我们系统的业务无关,主要是让同学们快速熟悉系统的
*/
@Service
public class ReviewServiceImpl implements ReviewService {
@Autowired
private MybatisReviewMapper reviewMapper;
/**=========================================================保存数据的方法=============================================*/
/**
* 保存数据的方法
* 需要结合异常处理
* @param name
* @param age
* @param sex
* @return
*/
@Override
public String saveData(String name, String age, String sex) {
try {
int i = reviewMapper.saveData(name, age, sex);
//这里演示全局异常处理 GlobalExceptionHandler 对指定异常的处理
// throw new Exception();
return "成功插入:" + i + "条数据";
}catch (Exception e){
throw new CustomException("数据插入失败");
}
}
/**
* 该方法使用对象进行保存数据
* 在该方法位置可以通过BeanUtils.copyProperties的方式进行对象属性的填充
* @param reviewVO 前端传入对象
* @return
*/
@Override
public String saveData(MybatisReviewVO reviewVO) {
try {
Review review = new Review();
BeanUtils.copyProperties(reviewVO,review);
int i = reviewMapper.saveDataByPojo(review);
//这里演示全局异常处理 GlobalExceptionHandler 对指定异常的处理
// throw new Exception();
return "成功插入:" + i + "条数据";
}catch (Exception e){
throw new CustomException("数据插入失败");
}
}
/**=========================================================删除数据=============================================*/
/**
* 删除数据的方法
* @param id
* @return
*/
@Override
public String removeData(Long id) {
int i = reviewMapper.removeData(id);
return "成功删除:" + i + "条数据";
}
/**=========================================================修改数据=============================================*/
/**
* 修改数据的方法
* @param reviewVO
* @return
*/
@Override
public String updateData(MybatisReviewVO reviewVO) {
try {
Review review = new Review();
BeanUtils.copyProperties(reviewVO,review);
reviewMapper.updateData(review);
return "修改成功";
}catch (Exception e){
throw new CustomException("修改失败");
}
}
/**=========================================================查询数据的方法=============================================*/
/**
* 根据id查询数据的方法
* @param id
* @return
*/
@Override
public Review getDataById(Long id) {
return reviewMapper.getById(id);
}
/**
* 分页查询数据的方法
* @return
*/
@Override
public List<Review> getDataByPage() {
return reviewMapper.getDataByPage();
}
}
3.4mapper
package com.huike.review.mapper;
import com.huike.review.pojo.Review;
import com.huike.review.vo.MybatisReviewVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* Mybatis复习的Mapper层
*/
public interface MybatisReviewMapper {
/**======================================================新增======================================================**/
/**
* 通过简单参数的方式保存对象的方法
* @param name
* @param age
* @param sex
* @return
*/
int saveData(@Param("name") String name,@Param("age") String age,@Param("sex") String sex);
/**
* 通过实体类保存数据的方法
* @param data 实体类
* @return
*/
int saveDataByPojo(Review data);
/**======================================================删除======================================================**/
/**
* 根据id删除操作
* @param id
* @return
*/
Integer removeData(@Param("id")Long id);
/**======================================================修改======================================================**/
/**
* 修改数据的方法
* @param review
* @return
*/
int updateData(Review review);
/**======================================================简单查询===================================================**/
/**
* 根据id查询对应的数据
* @param id
* @return
*/
Review getById(@Param("id") Long id);
/**
* 分页查询数据的方法
* @return
*/
List<Review> getDataByPage();
}
3.5xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.huike.review.mapper.MybatisReviewMapper">
<sql id="reviewSQL">
SELECT id,name,age,sex,create_by as createBy,create_time as createTime,update_time ,update_user as updateBy FROM `mybatis_review`
</sql>
<insert id="saveDataByPojo" parameterType="com.huike.review.pojo.Review">
INSERT INTO `mybatis_review` (`name`,`age`,`sex`) VALUES (#{name},#{age},#{sex})
</insert>
<insert id="saveData">
INSERT INTO `mybatis_review` (`name`,`age`,`sex`) VALUES (#{name},#{age},#{sex})
</insert>
<update id="updateData" parameterType="com.huike.review.pojo.Review">
UPDATE `mybatis_review` SET `name` = #{name},age = #{age},sex = #{sex} WHERE id = #{id}
</update>
<delete id="removeData">
DELETE FROM `mybatis_review` WHERE id = #{id}
</delete>
<select id="getById" resultType="com.huike.review.pojo.Review" parameterType="Long">
<include refid="reviewSQL"></include> WHERE id = #{id}
</select>
<select id="getDataByPage" resultType="com.huike.review.pojo.Review">
<include refid="reviewSQL"></include>
</select>
</mapper>
4.如何高效的看代码(idea标签)
标记书签
ctrl+f11 后按 0~9 a~z 提供了这么多的书签
设置0号标签 ctrl+f11后按0
快速跳转到标签
假设之前设置了0号标签
跳转到0号标签 ctrl+0
刪除标签
选择标签所在行按F11