在将它们添加到 MongoDB 之前,如何在 Spring Data 中处理插入请求?
Posted
技术标签:
【中文标题】在将它们添加到 MongoDB 之前,如何在 Spring Data 中处理插入请求?【英文标题】:How to process insert requests in Spring Data before adding them to MongoDB? 【发布时间】:2015-10-27 22:27:01 【问题描述】:在遵循https://spring.io/guides/gs/accessing-mongodb-data-rest/ 的非常有用的教程之后,我正在尝试创建一个链接缩短器应用程序。我编写了一个 URL 类(带有 id
、longURL
和 hash
属性)和 URLRepository 类(目前,只有 findByHash
方法,如演示中所示)。请注意,“散列”是指由尚未实现的方法生成的随机短字符串,而不是像 MD5 这样的实际散列函数。例如,只需致电独立的generateHash(String URL)
我可以使用 Spring 提供的 REST 接口将新条目添加到数据库中,也可以获取它们。但是,我想让应用程序自己生成哈希并在存储之前进行一些检查和处理 - 主要检查 URL 是否尚未存储,在这种情况下它只会返回现有的哈希。
我想我必须在我的URLRepository
类下扩展SimpleMongoRepository
的<S extends T> List<S> save(Iterable<S> entites);
方法(由MongoRepository
扩展),但我不确定该怎么做。我也看到了insert
方法,不知道应该用哪个
URL.java
public class URL
@Id private String id;
private String longURL;
private String hash;
public String getLongURL()
return longURL;
public void setLongURL(String longURL)
this.longURL = longURL;
public String getHash()
return hash;
public void setHash(String Hash)
this.hash = Hash;
URLRepository.java
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.util.Assert;
@RepositoryRestResource(collectionResourceRel = "urls", path = "urls")
public interface URLRepository extends MongoRepository<URL, String>
List<URL> findByHash(@Param("hash") String hash);
【问题讨论】:
不,扩展SimpleMongoRepository
通常不是要走的路。您介意在您要实现的目标上添加一些示例(伪)吗?从散文中消化有点困难。另外“让应用程序自己生成哈希”到底是什么意思?目前是如何获取hash的?
我会马上给我的代码做广告,对不起!目前,我可以发送一个包含所需长 URL 及其哈希的 POST 请求。但是我想要的是只发送长 URL 并让应用程序以任何方式生成哈希(不必是实际的哈希,它可以是随机字符串或其他任何东西,实现尚未完成并且是开放的未来的变化)
一个很酷的功能是允许提交两种类型的链接:(a) 长 URL 并让应用程序生成并返回其哈希值,或者 (b) 发送长 URL 和建议的哈希值,让应用程序返回散列本身,或者如果散列已经存在/无效/发生其他问题,则会出现错误消息。但我很高兴至少现在有选项(a)。
【参考方案1】:
感觉你最好编写一个自定义控制器而不是在这里使用 Spring Data REST,因为你基本上需要两个资源:一个用于添加链接或返回现有的,第二个用于通过其哈希检索原始 URI .
在第一种方法中,您只需调用存储库方法findByLongURL(…)
并使用获得的URL
实例,如果您有结果或采取第二步实际创建哈希并保存URL
实例思想存储库.第二个资源基本上只是调用你已经存在的方法。
这很简单,很容易消化。
如果您需要将前一种方法实现为原子操作,则需要手动实现存储库查询方法(有关一般说明,请阅读reference documentation 中的相关部分):
class UrlRepositoryImpl implements UrlRepositoryCustom
private final MongoOperations operations;
public UrlRepositoryImpl(MongoOperations operations)
this.operations = operations;
@Override
public URL findOrInsert(String source)
// What to find?
Query query = Query.query(Criteria.where("longURL").is(source);
// What to write if nothing can be found
Update update = new Update()
.setOnInsert("longURL", source)
.setOnInsert("hash", calculatedHash);
FindAndModifyOptions options = new FindAndModifyOptions.options()
.returnNew(true) // returns the document insert (if so)
.upsert(true); // insert document if it doesn't exist
return operations.findAndModify(query, update, options, URL.class);
如您所见,这涉及处理一些较低级别的细节(尽管可以通过使用静态导入来减少冗长),但基本上为您提供了原子操作。
【讨论】:
为了帮助像我这样的新手,我找到了here 一些有用的例子来了解我必须编写的控制器的结构。 我确实在 UrlController 类下实现了一个自定义控制器,并将我的控制器映射到处理 /api/urls 上的请求,这很好。但是,我仍然可以在没有任何验证的情况下向 /urls 发布请求。我怎样才能避免这种行为?而且我无法将某些静态页面映射到 /urls,因为这是我的重定向系统将运行的地方,将 /xyzabc 转换为正确的 URL 这是应用程序记录的内容: DispatcherServlet with name 'dispatcherServlet' processing POST request for [/urls] -- 查找路径 /urls 的处理程序方法 -- 未找到 [/urls 的处理程序方法] -- Null ModelAndView 返回到 DispatcherServlet,名称为 'dispatcherServlet':假设 HandlerAdapter 完成请求 -- 成功完成请求以上是关于在将它们添加到 MongoDB 之前,如何在 Spring Data 中处理插入请求?的主要内容,如果未能解决你的问题,请参考以下文章
在将其发送到视图(节点 js)之前,无法更改路由中 MongoDB/MongooseJS 的结果