我有一个用JavaEE编写的项目,但我是该技术的新手。
我的EJB依赖于从客户端前端收到的参数。
目前,我正在验证EJB中的参数,例如,我在EJB中有方法来验证参数,但我认为这是不好的做法,因为它导致代码重复,并为我的EJB增加了更多的职责
我想知道执行参数验证的最佳做法是什么。
编辑:客户端无法直接访问我的JavaEE后端。相反,我们有一个用Java编写的互操作性层,遵循SOAP架构,位于客户端前端和J2E后端之间。
我的代码示例如下:
// Method inherited from the EJB interface
// The eventOrganizer variable is another EJB that is injected into this very EJB
@Override
public boolean registerEvent(String name, int participantNumber, Calendar date, Coordinator coordinator) {
l.log(Level.INFO, "Received request for event creation");
if (!areParametersValid(name, participantNumber, date, coordinator)) {
return false;
}
Calendar cal = Calendar.getInstance();
cal.setTime(date.getTime());
cal.add(Calendar.HOUR_OF_DAY, 12);
Event event = new Event(coordinator, date.getTime(), cal.getTime(), participantNumber, name);
return eventOrganizer.bookRoom(event);
}
// Parameters validation methods
/**
* Returns true if the given name is non null and
* is not empty
* @param name the name of the {@link Event}
* @return true if the name semantically of the {@link Event} is valid
*/
private boolean nameIsGood(String name) {
return name != null && !name.trim().equals("");
}
/**
* Returns true if the number of participant is strictly positive
* @param participantNumber the number of people in the {@link Event}
* @return true if the number of participant is valid
*/
private boolean participantNumberIsGood(int participantNumber) {
return participantNumber > 0;
}
/**
* Checks if the given date is a date in the future,
* and returns true if it is
* @param date the date to check
* @return true if the provided start date for the {@link Event} is valid
*/
private boolean dateIsGood(Calendar date) {
return date.after(Calendar.getInstance());
}
/**
* Checks if the given {@link Coordinator} is a valid coordinator,
* i.e., if he's not null, and returns true if he is not
* @param coordinator the {@link Coordinator} to check
* @return true if the {@link Coordinator} is valid
*/
private boolean coordinatorIsGood(Coordinator coordinator) {
return coordinator != null;
}
/**
* Checks that all the parameters received for an {@link Event} creation are valid
* and returns true if they are, or false if they're not
* @param name the name of the {@link Event}, as a {@link String}
* @param participantNumber the estimated number of people for the
* {@link Event} as a {@link Integer}
* @param date the date at which the {@link Event} is scheduled,
* as a {@link Calendar}
* @param coordinator the {@link Coordinator} that created the {@link Event}
* @return true if all the given parameters are valid, and the event creation shall be processed
*/
private boolean areParametersValid(String name, int participantNumber, Calendar date, Coordinator coordinator) {
return nameIsGood(name) && participantNumberIsGood(participantNumber) && dateIsGood(date) && coordinatorIsGood(coordinator);
}
// Event object
public class Event {
private Coordinator coordinator;
private Date startDate;
private Date endDate;
private int nbPeople;
private String name;
private List<Room> rooms;
private List<RoomType> desiredRoomTypes;
public Event(int nbPeople, String name, List<RoomType> roomTypes) {
this.nbPeople = nbPeople;
this.name = name;
this.desiredRoomTypes = roomTypes;
this.rooms = new ArrayList<>();
}
public Event(Coordinator coordinator, Date startDate, Date endDate, int nbPeople, String name) {
this.coordinator = coordinator;
this.startDate = startDate;
this.endDate = endDate;
this.nbPeople = nbPeople;
this.name = name;
this.rooms = new ArrayList<>();
}
public List<Room> getRooms() {
return rooms;
}
public void addRooms(List<Room> rooms) {
this.rooms.addAll(rooms);
}
public void addRoom(Room room) {
this.rooms.add(room);
}
public Coordinator getCoordinator() {
return coordinator;
}
public Date getStartDate() {
return startDate;
}
public Date getEndDate() {
return endDate;
}
public int getNbPeople() {
return nbPeople;
}
public String getName() {
return name;
}
}
// Coordinator object
public class Coordinator {
private String firstName;
private String lastName;
private String email;
private List<Event> eventsCreated;
public Coordinator(String firstName, String lastName, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
public List<Event> getEventsCreated() {
return eventsCreated;
}
public void setEventsCreated(List<Event> eventsCreated) {
this.eventsCreated = eventsCreated;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getEmail() {
return email;
}
}
答案 0 :(得分:0)
避免混乱的一种方法是将未经验证的(可变)对象与经过验证的(不可变)对象分开。不要害怕根据需要拥有多个不可变对象。 验证的行为是确定您拥有哪些数据,并通过扩展来确定它实际上是什么类型/对象。
至于它自己的验证,如果它的用户反馈使一个方法给一些对象提供所有问题并传递它。这样,您就可以使用相同的界面验证所有对象。
UserFeedbackObject validate(UserFeedbackObject f){
if (name.length == 0) f = f.badField("username","expected a username");
if (date.after(Calendar.getInstance()) == 0) f = f.badField("username","date needs to be in the future");
return f;
}
答案 1 :(得分:0)
一旦您正在寻找良好做法,我强烈建议您使用Bean Validation而不是编写自己的验证机制,特别是对于简单约束。
Bean Validation是Java EE的一部分。它基于注释,并带有built-in set of constraints。如果他们不适合你,你可以编写自己的约束。
根据您当前的验证限制,您将拥有以下内容:
Event registerEvent(@NotNull @NotBlank String name,
@Min(1) int participantNumber,
@NotNull @Future Calendar date,
@NotNull @Valid Coordinator coordinator);
Bean验证是规范。实际验证由实现执行,例如Hibernate Validator。如何设置Bean Validation或Hibernate Validator超出了这个答案的范围。
一些有用的资源:
答案 2 :(得分:-1)
由于专注于业务逻辑bean 或可重用性等多种原因,我决定将字段验证委托给拦截器
我在一个名为FieldsValidator
的帮助器类中提取了验证方法,我在拦截器中使用了它。
这种剪纸提供了三件事:
验证和测试的逻辑仅针对一个类进行,例如,
FieldsValidator
。
拦截器专注于验证和WebFault
例外
抛
Beans现在只关心业务逻辑,参数完整性/有效性是在可重复使用的拦截器中完成的
查找以下示例:
验证String不为空且不为空的拦截器:
@AroundInvoke
public Object intercept(InvocationContext ctx) throws Exception {
Object[] parameters = ctx.getParameters();
// loops through the parameters of the method
for (Object parameter : parameters) {
if (parameter == null) {
throw new InvalidRequestParametersException("One or more parameters of type String in the request are null!");
}
// if the parameter is of type String
if (parameter.getClass().getName().equals(String.class.getName())) {
// if the string is invalid
if (!FieldsValidator.isStringValid((String) parameter)) {
throw new InvalidRequestParametersException("One or more parameters of type String in the request are invalid!");
}
}
}
return ctx.proceed();
}
以下是我的FieldsValidator类的示例:
/**
* A static helper class used to validate fields within the EJBs
*
* @author Maxime Flament (maxime.flament@etu.unice.fr)
*/
public class FieldsValidator {
/**
* Returns true if the given string is non null and
* is not empty
*
* @param str the string to validate
* @return true if the string is semantically correct
*/
public static boolean isStringValid(String str) {
return str != null && !str.equals("");
}
/**
* Returns true if the given value is strictly positive
*
* @param value the number to check
* @return true if the value is strictly positive
*/
public static boolean isStrictlyPositive(int value) {
return value > 0;
}
/**
* Checks if the given date is a date in the future,
* and returns true if it is
*
* @param date the date to check
* @return true if the provided start date is valid
*/
public static boolean dateIsGood(Calendar date) {
return date.after(Calendar.getInstance());
}
/**
* Checks if the given {@link Object} is a valid object,
* i.e., if he's not null, and returns true if he is not
* @param object the {@link Object} to check
* @return true if the {@link Object} is valid
*/
public static boolean isObjectNotNull(Object object) {
return object != null;
}
/**
* Checks that the provided email is correct, and returns true if it is,
* or false otherwise
*
* @implNote this method doesn't check that the provided email
* actually exists, but it only checks if the email
* is valid according to the RFC
*
* <a href="https://stackoverflow.com/a/26687649/5710894">Inspired by this</a>
*
* @param email the email to check
* @return true if the given email is valid
*/
public static boolean isValidEmail(String email) {
return EmailValidator.getInstance().isValid(email);
}
}
下面是我的一个bean中拦截器使用的一个例子:
@Interceptors({InterceptorStringVerifier.class /* Add more interceptors here */})
Event registerEvent(String name, int participantNumber, Calendar date, Coordinator coordinator)
注意:拦截器应始终在bean的接口中声明,而不是实现。