Spring 学习框架原理java所有基础知识

springboot项目目前设计的技术点

2018-10-31  本文已影响331人  简单coder

maven依赖

项目配置方面

项目模块(从dao层往前翻)

数据库这块(这些都是我踩过的坑)


文章部分这里使用text格式存储,这里要注意一点,text在逆向时会生成blob格式,这不是我们想要的varchar格式,我们得指定转成varchar格式

<table tableName="t_article" domainObjectName="Article" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false">
            <columnOverride column="content" jdbcType="VARCHAR" />
        </table>

时间这块用datetime,创建有默认时间,更新随时间更新更新

CREATE TABLE `t_article` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `title` varchar(200) DEFAULT NULL COMMENT '标题',
  `titlePic` varchar(100) DEFAULT NULL COMMENT '标题图片',
  `content` text COMMENT '主题内容',
  `author_id` int(11) DEFAULT NULL COMMENT '用户id',
  `type` varchar(16) DEFAULT NULL COMMENT '类型',
  `status` int(1) DEFAULT NULL COMMENT '状态:0-未发布,1-已发布,2-已撤销',
  `category_id` int(11) DEFAULT NULL COMMENT '类型id',
  `category_name` varchar(20) DEFAULT NULL COMMENT '类型名称',
  `allow_comment` tinyint(1) DEFAULT '0' COMMENT '允许评论:0-允许,1-不允许',
  `like_count` int(11) DEFAULT '0' COMMENT '点赞数',
  `collect_count` int(11) DEFAULT '0' COMMENT '收藏数',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

评论

评论这款我加了个ip字段,因为评论不需要登录,为了防止有人狂刷接口,这里我用ip禁止,每个ip不能重复发表评论

CREATE TABLE `t_comment` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `address_ip` varchar(30) NOT NULL COMMENT '评论ip,防刷接口',
  `article_id` int(11) NOT NULL COMMENT '文章id',
  `parent_id` int(11) DEFAULT NULL COMMENT '父评论',
  `content` varchar(50) NOT NULL COMMENT '评论内容',
  `person_id` int(11) DEFAULT NULL COMMENT '评论人id',
  `status` int(2) DEFAULT '0' COMMENT '评论状态:0-正常,1-删除',
  `like_count` int(11) DEFAULT '0' COMMENT '点赞数',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `name` varchar(50) DEFAULT NULL COMMENT '昵称',
  `icon` varchar(200) DEFAULT 'https://upload.jianshu.io/users/upload_avatars/7290998/f64f5ef0-def0-4b26-beb3-b9d88f060ba0.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240' COMMENT '头像',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

t_log这块,之前我想把错误数据打到数据库内,后来懒得做了,直接本地化存储.........其实要做也是可以的,我做了errorlog处理,这个后面再谈

数据库总结:
第一次设计数据库,真的很没有经验,我基本上是边写边改字段,然后边重新生成mapper,xml,pojo,这里我希望给没有那么多经验的人一个警示:设计一个表的时候,一定要考虑好状态这个点,这个表对应的实体有什么状态呢,比如上架,下架,审核未审核,删除未删除,这些都要有状态!

DAO层:

<insert id="insert" parameterType="com.ipaozha.crm.pojo.Category" useGeneratedKeys="true" keyColumn="category_id"
          keyProperty="categoryId">
User login(@Param("username") String username,@Param("password") String md5Password);

DAO层总结:
这块儿没什么好说,sql多写写即可

Service层:

//这里还需要当前用户的信息
        User user = CrmUtils.getLoginUser(request);
        if (null == user) {
            throw new CrmAuthException();
        }
        try {
            //取值
            Article article = new Article();
            BeanUtils.copyProperties(articleForm, article);
            article.setContent(articleForm.getText());
            article.setAuthorId(user.getId());

            int result = articleMapper.insertSelective(article);
            if (result > 0) {
                return article;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new CrmException(RespEnum.article_insert_error);
        }
} catch (Exception e) {
       e.printStackTrace();
       throw new CrmException(450, e.getMessage());
}

service总结:
这块真的很重要,很多很多的逻辑都是这块儿处理的,希望大家做的时候多思考

controller层

import lombok.Data;

import javax.validation.constraints.NotNull;

@Data
public class CommentForm {

    @NotNull(message = "文章id不能为空")
    private Integer articleId;

    @NotNull(message = "昵称不能为空")
    private String name;

    @NotNull(message = "评论内容不能为空")
    private String content;

    private Integer parentId;

    private Integer personId;

    private String addressIp;

}
@RequestMapping("/article/{id}")
    public String article(@PathVariable("id") Integer id, Map<String, Object> map) {

controller总结
注意结构清晰即可

exception处理

@Data
public class CrmException extends Exception{

    private Integer code;

    public CrmException(RespEnum respEnum) {
        super(respEnum.getMsg());
        this.code = respEnum.getCode();
    }

    public CrmException(Integer code, String msg) {
        super(msg);
        this.code = code;
    }
}
@ControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(CrmException.class)
    @ResponseBody
    public Resp handleException(CrmException exception) {
        return Resp.error(exception.getCode(), exception.getMessage());
    }

    @ExceptionHandler(CrmAuthException.class)
    public String hanleAuthException(CrmAuthException exception) {
        return "/admin/login";
    }

}

spring已经为我们做好了一切,只需稍微配置即可

拦截器处理

@Slf4j
@Component
public class AdminInterceptor implements HandlerInterceptor {

    private  String baseImg = "/upload";


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
        String uri = request.getRequestURI();
        // 这里传过去basePath的一些参数
        request.getSession().setAttribute("base", "");
        request.getSession().setAttribute("baseImg", baseImg);

//        log.info(String.valueOf(request.getSession().getMaxInactiveInterval()));
        log.info("UserAgent: {}", request.getHeader("user-agent"));
        log.info("用户访问地址: {}, 来路地址: {}", uri, IPKit.getIpAddrByRequest(request));
        //请求拦截处理
        User user = CrmUtils.getLoginUser(request);
        if (uri.startsWith("/admin") && !uri.startsWith("/admin/login") && null == user
                && !uri.startsWith("/admin/css") && !uri.startsWith("/admin/images")
                && !uri.startsWith("/admin/js")) {
            response.sendRedirect(request.getContextPath() + "/admin/login");
            return false;
        }

        //先在这里存一下user
        request.setAttribute("user", user);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

    }
}

@Component
public class WebMVCConfig implements WebMvcConfigurer {

@Autowired
private AdminInterceptor adminInterceptor;


@Value("${web.upload}")
private String rootPath;

/**
 * 不需要登录拦截的url:登录注册
 */
final String[] notLoginInterceptPaths = {"/upload/**","/admin/login","/admin/regist"};

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(adminInterceptor).addPathPatterns("/**").excludePathPatterns("/upload/**","/admin/login","/admin/regist","/error");

}


@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    //这里是用来处理upload文件的文件地址访问,因为上传的图片等在项目外
    registry.addResourceHandler("/upload/**").addResourceLocations("file:"+rootPath + "/");
}

}

项目目录:


其实目前我的boot项目弊端已经体现出来了,controller,service,dao层太过厚重了,一个功能可能要多很多个文件,项目也越来越厚,但是没办法,目前我这个是单模块web项目,后续我会再起一个项目(或者直接在这个项目上修改),直接越过maven模块(因为这块已经做过),向spring cloud前进!

这篇博客我后面也会同步到我搭建的博客网站,欢迎大家比较,指正!(本博客暂未开通emoji表情,希望大家文章内别带emoji表情,不然是创建不成功的)
博客链接

上一篇下一篇

猜你喜欢

热点阅读