创新实训 4

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值