网站建设投标人资质要求,王野天个人资料,河间做网站,做足球经理头像的网站目录
第八章 文章管理模块
8.1 配置文件
8.2 视图文件
8.3 Java代码 第八章 文章管理模块
创建新的Spring Boot项目#xff0c;综合运用视频中的知识点#xff0c;做一个文章管理的后台应用。 新的Spring Boot项目Lession20-BlogAdmin。Maven构建工具#xff0c;包…目录
第八章 文章管理模块
8.1 配置文件
8.2 视图文件
8.3 Java代码 第八章 文章管理模块
创建新的Spring Boot项目综合运用视频中的知识点做一个文章管理的后台应用。 新的Spring Boot项目Lession20-BlogAdmin。Maven构建工具包名称com.bjpowernode.blog JDK19依赖
Spring WebLombokThymeleafMyBatis FrameworkMySQL Driver
依赖还需要Bean Validation 需求文章管理工作发布新文章编辑文章查看文章内容等
8.1 配置文件
组织配置文件 app-base.yml
article:#最低文章阅读数量low-read: 10#首页显示最多的文章数量top-read: 20db.yml
spring:datasource:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/blog?serverTimezoneAsia/Shanghaiusername: rootpassword: 123456hikari:auto-commit: truemaximum-pool-size: 10minimum-idle: 10#获取连接时检测语句connection-test-query: select 1connection-timeout: 20000#其他属性data-source-properties:cachePrepStmts: truedataSource.cachePrepStmtst: truedataSource.prepStmtCacheSize: 250dataSource.prepStmtCacheSqlLimit: 2048dataSource.useServerPrepStmts: true8.2 视图文件
logo文件 favicon.ico放在static/ 根目录下
创建模板页面 articleList.html
!DOCTYPE html
html langen xmlns:thhttp://www.thymeleaf.org
headmeta charsetUTF-8title文章列表/titlelink relicon href../favicon.ico typeimage/x-icon/script srchttps://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js/script
/head
bodydiv stylemargin-left: 200pxh3阅读最多的前10篇文章/h3table border1px cellspacing0px cellpadding2pxtheadth选择/thth序号/thth标题/thth副标题/thth已读数量/thth发布时间/thth最后修改时间/thth编辑/th/theadtbodytr th:eacharticle,loopStats : ${articleList}tdinput typecheckbox th:value${article.id}/tdtd th:text${loopStats.index1}/tdtd th:text${article.title}/tdtd th:text${article.summary}/tdtd th:text${article.readCount}/tdtd th:text${article.createTime}/tdtd th:text${article.updateTime}/tdtda th:href{/article/get(id${article.id})}编辑/a/td/trtrtd colspan8table width100%trtdbutton idadd onclickaddArticle()发布新文章/button/tdtdbutton iddelete onclickdeleteArticle()删除文章/button/tdtdbutton idread onclickreadOverview()文章概览/button/td/tr/table/td/tr/tbody/tableform idfrm th:action{/view/addArticle} methodget/formform iddelfrm th:action{/article/removeArticle} methodpostinput typehidden ididsDom nameids value /form/divscript typetext/javascriptfunction addArticle(){$(#frm).submit();}function deleteArticle(){var ids [];$(input[typecheckbox]:checked).each( (index,item){ids.push( item.value );})$(#idsDom).val(ids);$(#delfrm).submit();}function readOverview(){var ids [];$(input[typecheckbox]:checked).each( (index,item){ids.push( item.value );})if( ids.length ! 1){alert(选择一个文章查看);return;}$.get(../article/detail/overview, { id:ids[0] }, (data,status){alert(data)} )}/script
/body
/htmlbind.html
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
bodydiv stylemargin-left: 200pxdiv th:eachfield:${errors}div th:text${field.field}/divdiv th:text${field.defaultMessage}/div/div/div
/body
/htmlerror.html
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
bodydiv stylemargin-left: 200pxdiv th:text${error}/div/div
/body
/html8.3 Java代码 java代码
model包 ArticleVO.java
Data
public class ArticleVO {private Integer id;private Integer userId;private String title;private String summary;private String content;private Integer readCount;private LocalDateTime createTime;private LocalDateTime updateTime;
}ArticleParam.java
package com.bjpowernode.blog.model.param;import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.awt.PageAttributes.MediaType;
import lombok.Data;
import lombok.NonNull;
import org.hibernate.validator.constraints.Range;Datapublic class ArticleParam {public static interface AddArticle {};public static interface EditArticle {};NotNull(message 修改时必须有id,groups EditArticle.class)Min(value 1,message id必须从{value}开始,groups EditArticle.class)private Integer id;NotBlank(message 请输入文章标题,groups { AddArticle.class, EditArticle.class })Size(min 2,max 20,message 文章标题{min}-{max},groups { AddArticle.class, EditArticle.class })private String title;NotBlank(message 请输入文章副标题,groups { AddArticle.class, EditArticle.class })Size(min 10,max 30,message 文章副标题{min}-{max},groups { AddArticle.class, EditArticle.class })private String summary;NotBlank(message 请输入文章副标题,groups { AddArticle.class, EditArticle.class })Size(min 50,max 8000,message 文章至少五十个字,文章至多八千字,groups { AddArticle.class, EditArticle.class })private String content;
}ArticleDTO.java
Data
public class ArticleDTO {private Integer id;private Integer userId;private String title;private String summary;private Integer readCount;private String content;private LocalDateTime createTime;private LocalDateTime updateTime;
}po包 ArticlePO.java
Data
public class ArticlePO {private Integer id;private Integer userId;private String title;private String summary;private Integer readCount;private LocalDateTime createTime;private LocalDateTime updateTime;
}ArticleDetailPO.java
Data
public class ArticleDetailPO {private Integer id;private Integer articleId;private String content;
}mapper包 ArticleMapper.java
package com.bjpowernode.blog.mapper;public interface ArticleMapper {Select(select id,user_id,title,summary,read_count,create_time,update_timefrom articlewhere read_count #{lowRead}order by read_count desclimit #{topRead})Results(id ArticleBaseMap, value {Result(id true, column id, property id),Result(column user_id, property userId),Result(column title, property title),Result(column summary, property summary),Result(column read_count, property readCount),Result(column create_time, property createTime),Result(column update_time, property updateTime),})ListArticlePO topSortByReadCount(Integer lowRead, Integer topRead);Insert(insert into article(user_id,title,summary,read_count,create_time,update_time) \values(#{userId},#{title},#{summary},#{readCount},#{createTime},#{updateTime}))Options(useGeneratedKeys true, keyProperty id, keyColumn id)int insertArticle(ArticlePO articlePO);Insert(insert into article_detail(article_id, content) values (#{articleId},#{content}) )int insertArticleDetail(ArticleDetailPO articleDetailPO);Select(select m.id as articleId,title,summary,content from article m left join article_detail ad on m.id ad.article_idwhere m.id#{id})Results({Result(id true, column articleId, property id),Result(column title, property title),Result(column summary, property summary),Result(column content, property content, jdbcType JdbcType.LONGVARCHAR, javaType String.class)})ArticleDTO selectArticleAndDetail(Integer id);//更新文章titlesummaryUpdate(update article set title#{title},summary#{summary} where id#{id})int updateArticle(ArticlePO articlePO);Update(update article_detail set content#{content} where article_id#{articleId})int updateArticleDetail(ArticleDetailPO articleDetailPO);//script动态sql/scriptDelete(scriptdelete from article where id inforeach itemid collectionlist open( separator, close)#{id}/foreach/script)int deleteArticle(ListInteger ids);Delete(scriptdelete from article_detail where id inforeach itemid collectionlist open( separator, close)#{id}/foreach/script)int deleteArticleDetail(ListInteger ids);Select(select id,article_id,content from article_detailwhere article_id #{id})ArticleDetailPO selectDetailByArticleId(Integer id);
}ArticleService.java
public interface ArticleService {ListArticlePO queryTopAritcle();boolean addArticle(ArticleDTO article);boolean modifyArticle(ArticleParam param);int removeArticle(ListInteger ids);ArticleDTO queryByArticleId(Integer id);String queryTop20Detail(Integer id);
}ArticleServiceImpl.java
RequiredArgsConstructor
Service
public class ArticleServiceImpl implements ArticleService {private final ArticleMapper articleMapper;private final ArticleSettings articleSettings;Overridepublic ListArticlePO queryTopAritcle() {Integer lowRead articleSettings.getLowRead();Integer topRead articleSettings.getTopRead();return articleMapper.topSortByReadCount(lowRead, topRead);}Transactional(rollbackFor Exception.class)Overridepublic boolean addArticle(ArticleDTO article) {ArticlePO articlePO new ArticlePO();articlePO.setTitle(article.getTitle());articlePO.setSummary(article.getSummary());//从登陆信息中获取现在给个默认articlePO.setUserId(new Random().nextInt(1000));articlePO.setReadCount(new Random().nextInt(50));articlePO.setCreateTime(LocalDateTime.now());articlePO.setUpdateTime(LocalDateTime.now());articleMapper.insertArticle(articlePO);ArticleDetailPO articleDetailPO new ArticleDetailPO();articleDetailPO.setArticleId(articlePO.getId());articleDetailPO.setContent(article.getContent());articleMapper.insertArticleDetail(articleDetailPO);return true;}Transactional(rollbackFor Exception.class)public boolean modifyArticle(ArticleParam param){ArticlePO articlePO new ArticlePO();articlePO.setId(param.getId());articlePO.setTitle(param.getTitle());articlePO.setSummary(param.getSummary());int editArticle articleMapper.updateArticle(articlePO);ArticleDetailPO detailPO new ArticleDetailPO();detailPO.setArticleId(param.getId());detailPO.setContent(param.getContent());int editDetail articleMapper.updateArticleDetail(detailPO);if( editArticle 0 editDetail 0 ){return true;}return false;}Transactional(rollbackFor Exception.class)Overridepublic int removeArticle(ListInteger ids) {int master articleMapper.deleteArticle(ids);int detail articleMapper.deleteArticleDetail(ids);return master;}Overridepublic ArticleDTO queryByArticleId(Integer id) {return articleMapper.selectArticleAndDetail(id);}Overridepublic String queryTop20Detail(Integer id) {ArticleDetailPO articleDetailPO articleMapper.selectDetailByArticleId(id);String content articleDetailPO.getContent();if(StringUtils.hasText(content)){content content.substring(0, content.length() 20 ? 20 : content.length());}return content;}
}ArticleController.java
RequiredArgsConstructor
Controller
public class ArticleController {private final ArticleService articleService;GetMapping( value {/, /article/hot})public String showHotArticle(Model model){ListArticlePO articlePOList articleService.queryTopAritcle();//转为VOListArticleVO articleVOList BeanUtil.copyToList(articlePOList, ArticleVO.class);//存储数据model.addAttribute(articleList, articleVOList);//视图return /blog/articleList;}//添加文章PostMapping(/article/add)public String addArticle(Validated(ArticleParam.AddArticle.class) ArticleParam param){ArticleDTO article new ArticleDTO();article.setTitle(param.getTitle());article.setSummary(param.getSummary());article.setContent(param.getContent());boolean add articleService.addArticle(article);return redirect:/article/hot;}//查询文章GetMapping(/article/get)public String queryById(Integer id, Model model){ArticleDTO articleDTO articleService.queryByArticleId(id);ArticleVO articleVO BeanUtil.copyProperties(articleDTO, ArticleVO.class);model.addAttribute(article,articleVO);return /blog/editArticle;}//修改文章PostMapping(/article/edit)public String modifyArticle(Validated(ArticleParam.EditArticle.class) ArticleParam param){boolean edit articleService.modifyArticle(param);return redirect:/article/hot;}//删除文章PostMapping(/article/removeArticle)public String removeArticle(RequestParam(ids) IdType idType){System.out.println(idsidType);if(idType.getIdList() null){throw new IdNullException(Id为null);}articleService.removeArticle(idType.getIdList());return redirect:/article/hot;}//查询文章开始的20个字GetMapping(/article/detail/overview)ResponseBodypublic String queryDetail(Integer id){String top20Content articleService.queryTop20Detail(id);return top20Content;}
}IdNullException.java
public class IdNullException extends BlogRootException{public IdNullException() {super();}public IdNullException(String message) {super(message);}
}BlogRootException.java
public class BlogRootException extends RuntimeException{public BlogRootException() {super();}public BlogRootException(String message) {super(message);}
}GlobalHandleException.java
ControllerAdvice
public class GlobalHandleException {ExceptionHandler( BindException.class)public String handlerBindException(BindException bindException, Model model){BindingResult result bindException.getBindingResult();if( result.hasErrors()){model.addAttribute(errors,result.getFieldErrors());System.out.println(result.getFieldErrors()result.getFieldErrors().size());}return /blog/error/bind;}ExceptionHandler( Exception.class)public String handlerDefaultException(Exception exception, Model model){model.addAttribute(msg,请稍后重试);return /blog/error/error;}
}IdType.java
Data
public class IdType {private ListInteger idList;
}IdTypeFormatter.java
public class IdTypeFormatter implements FormatterIdType {Overridepublic IdType parse(String text, Locale locale) throws ParseException {IdType idType new IdType();if(StringUtils.hasText(text)){ListInteger ids new ArrayList();for (String id : text.split(,)) {ids.add(Integer.parseInt(id));}idType.setIdList(ids);}return idType;}Overridepublic String print(IdType object, Locale locale) {return null;}
}ArticleSettings.java
Data
ConfigurationProperties(prefix article)
public class ArticleSettings {private Integer lowRead;private Integer topRead;
}WebMvcSettings.java
Configuration
public class WebMvcSettings implements WebMvcConfigurer {Overridepublic void addFormatters(FormatterRegistry registry) {registry.addFormatter(new IdTypeFormatter());}Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController(/view/addArticle).setViewName(/blog/addArticle);}
}启动类 Lession19AdminApplication.java
MapperScan(basePackages { com.bjpowernode.blog.mapper })
EnableConfigurationProperties( {ArticleSettings.class} )
SpringBootApplicationpublic class Lession19AdminApplication {public static void main(String[] args) {SpringApplication.run(Lession19AdminApplication.class, args);}}