2021SC@SDUSC
这次我们继续分析search-engine模块
DmsArticleController
这个类中只有一个接口
@RequestMapping("/findAll")
@ResponseBody
List<DmsArticle> findAll() {
return dmsArticleService.findAll();
}
其中我们可以看到他调用的时ArticleService服务层,继续深挖,我们可以知道ArticleService的服务如下:
public interface DmsArticleService {
DmsArticle save(DmsArticle dmsArticle);
List<DmsArticle> saveAll(List<DmsArticle> articles);
void delete(String id);
void update(DmsArticle dmsArticle);
Optional<DmsArticle> findOne(DmsArticle dmsArticle);
Optional<DmsArticle> findById(String id);
List<DmsArticle> findAll();
List<DmsArticle> findByBookname(String bookname);
List<DmsArticle> findByTitle(String title);
List<DmsArticle> findByArticleAuthor(String articleAuthor);
}
DmsArticle是一个实体类,其包含了一篇文章的:
- 唯一标识 String
- 文章作者 String
- 书名 String
- 内容 String
- 图片链接 String
- 页码 List<Map<String, String>>
- xml文档 String
- 文章注解 String
- 朝代 String
- 详细注解 JSONArray
查看DmsArticleService的实现,会发现他其实调用的是DmsArticleRepository的接口:
@Resource
private DmsArticleRepository dmsArticleRepository;
@Override
public DmsArticle save(DmsArticle dmsArticle) {
return dmsArticleRepository.save(dmsArticle);
}
...
继续深挖,我们会注意到DmsArticleRepository继承自MongoRepository
@Repository(value = "ds1DmsArticleRepository")
public interface DmsArticleRepository extends MongoRepository<DmsArticle,String> {
...
}
注意到这里MongoRepository泛型中有两个参数,分别是DmsArticle和String
追溯源码,我们会注意到。
@NoRepositoryBean public interface MongoRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> { ... }
而在MongoRepository中其实并没有用到ID这一泛型,观察接口中的使用情况,我们可以发现T应该指的是存储的数据类型。
再继续看:
@NoRepositoryBean public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> { // ... Iterable<T> findAll(Sort sort); /// ... Page<T> findAll(Pageable pageable); }
再继续看:
@NoRepositoryBean public interface CrudRepository<T, ID> extends Repository<T, ID> { ... // ... Optional<T> findById(ID id); ... }
这里我们就可以发现,ID应该是用来指明该文档的唯一标识符的类型。
最高层的接口也给出了答案:
/** * @param <T> the domain type the repository manages * @param <ID> the type of the id of the entity the repository manages */ @Indexed public interface Repository<T, ID> { }
DmsCharacterController
同DmsArticleController,只有一个findAll接口,结构几乎一致,这里不过多赘述。
PmsUserScoreRelationController
该类中有多个服务接口:
@RestController
@RequestMapping("/score")
public class PmsUserScoreRelationController {
@Autowired
private PmsUserScoreRelationRepository pmsUserScoreRelationService;
@PostMapping("/find")
public Object find(Integer uid){
Optional<PmsUserScoreRelation> pusrs = pmsUserScoreRelationService.findById(uid);
return pusrs.orElse(null);
}
@PostMapping("/delete")
public void delete(Integer uid){
pmsUserScoreRelationService.deleteById(uid);
}
@PostMapping("/update")
public String update(Integer uid, BigInteger score){
Optional<PmsUserScoreRelation> pusrs = pmsUserScoreRelationService.findById(uid);
if (pusrs.isPresent()) {
PmsUserScoreRelation pusr = pusrs.get();
pusr.setScore(score);
pmsUserScoreRelationService.save(pusr);
return "更新成功";
}else{
return "更新失败";
}
}
@PostMapping("/save")
public void save(Integer uid, BigInteger score){
PmsUserScoreRelation pusr = new PmsUserScoreRelation(uid, score);
System.out.println(pmsUserScoreRelationService.save(pusr));
}
}
显然,调用的是PmsUserScoreRelationRepository的服务,这次没有像之前那样用一个Service作为过度了,确实显得简介了不少。
进入PmsUserScoreRelationRepository,我们可以发现其继承自JpaRepository接口:
@Repository(value = "ds1PmsUserScoreRelationRepository")
public interface PmsUserScoreRelationRepository extends JpaRepository<PmsUserScoreRelation, Integer> {
}
可以发现,JpaRepository和MongoRepository十分相似,进去也可以发现这两个接口完全继承自两个相同的接口:
PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T>
这里我们可以讲述一下各自的工作原理,
Springboot对于数据库的访问做了非常大的优化,对于查找的实体类,我们只需要用注解进行标注即可
如MongoRepository的规范是:
@Document("dms_article") public class DmsArticle implements Serializable { @Id @Field("_id") private String _id; @Field("articleAuthor") @ApiModelProperty(value = "文章作者") private String articleAuthor; @Field("bookname") @ApiModelProperty(value = "书名") private String bookname; @Field("content") @ApiModelProperty(value = "内容") private String content; @Field("imgurl") @ApiModelProperty(value = "图片链接") private String imgUrl; ... }
而JpaRepository的规范是:
@Entity(name = "ds1PmsUserScoreRelation") @Table(name = "pms_user_point_relation") public class PmsUserScoreRelation implements Serializable { @Id @ApiModelProperty(value = "用户id") private Integer uid; @ApiModelProperty(value = "积分") private BigInteger score; }
其中Jpa面向的是关系型数据库,而MongoDB是一个非关系型数据库。
SmsSearchHistoryController
其结构和PmsUserScoreRelationController一致,提供的是搜索历史数据的查询。
实体类大致:
@Entity(name = "ds2SmsSearchHistory")
@Table(name = "sms_search_history")
public class SmsSearchHistory implements Serializable {
@Id
@ApiModelProperty(value = "搜索历史id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer hid;
@ApiModelProperty(value = "用户名")
private String username;
@ApiModelProperty(value = "搜索历史")
private String word;
@ApiModelProperty(value = "添加时间")
private String addTime;
@ApiModelProperty(value =
"1-模糊搜索作者\n" +
"2-模糊搜索标题\n" +
"3-模糊搜索原文\n" +
"4-精准搜索作者\n" +
"5-精准搜索标题\n" +
"6-精准搜索原文")
private Integer type;
}
使用的是Jpa框架
SmsUserBookmarkRelationController
这个Controller提供的服务依然是基于Jpa的关系型数据库(这里是mysql)的增删改查,不过有一个亮点在于他的service层的find方法实现处调用了另一台服务器的服务。
@Service
public class SmsUserBookmarkRelationServiceImpl implements SmsUserBookmarkRelationService {
@Autowired
SmsUserBookmarkRelationRepository smsUserBookmarkRelationRepository;
@Autowired
SmsArticleHeadRepository smsArticleHeadRepository;
@Override
public List<SmsArticleHead> find(String username) throws HttpStatusException {
List<SmsUserBookmarkRelation> findResult = smsUserBookmarkRelationRepository.findByUsername(username);
List<String> ids = new ArrayList<>();
for (SmsUserBookmarkRelation smsUserBookmarkRelation : findResult){
ids.add(smsUserBookmarkRelation.getAid());
}
String url = ".../mysql/article_head/findAllById";
Map<String, String> map = new HashMap<>();
map.put("ids", JSON.toJSONString(ids));
String httpResult = OkHttpUtil.doPost(url, map, "POST");
return JSONArray.parseArray(httpResult, SmsArticleHead.class);
}
...
}
做出了一点小更改,对于
List<SmsUserBookmarkRelation> findResult = smsUserBookmarkRelationRepository.findByUsername(username); List<String> ids = new ArrayList<>(); for (SmsUserBookmarkRelation smsUserBookmarkRelation : findResult){ ids.add(smsUserBookmarkRelation.getAid()); }
这步操作,我使用了流操作代替之前的操作
List<String> ids = findResult.stream().map(SmsUserBookmarkRelation::getAid).collect(Collectors.toList());
服务中涉及到了两个实体类,分别表示文章的头信息:
@Entity(name = "ds1SmsArticleHead")
@Table(name = "sms_article_head")
public class SmsArticleHead implements Serializable {
@Id
@ApiModelProperty(value = "文章头id")
private String aid;
@ApiModelProperty(value = "文章标题")
private String title;
@ApiModelProperty(value = "文章作者")
private String articleauthor;
@ApiModelProperty(value = "书名")
private String bookname;
@ApiModelProperty(value = "朝代")
private String dynasty;
}
和文章与提供用户的关系:
@Entity(name = "ds2SmsUserBookmarkRelation")
@Table(name = "sms_user_bookmark_relation")
public class SmsUserBookmarkRelation implements Serializable {
@Id
@ApiModelProperty(value = "用户名")
private String username;
@ApiModelProperty(value = "文章id")
private String aid;
@ApiModelProperty(value = "插入时间")
private String add_time;
}