Как в Java скрыть даже от разработчика поле, доступ к которому должен осуществляться с помощью геттера и/или сеттера
Много написано о том, что хорошей практикой является объявление полей экземпляра класса с модификатором private , а чтение и модификацию их осуществлять с помощью public геттера и/или сеттера. Действительно, этот приём даёт уверенность, что вся логика, предусмотренная разработчиком для событий чтения/записи, будет выполнена в случае использования класса кем-либо. Однако, разработчик класса в методах по-прежнему имеет возможность читать и записывать значение поля напрямую! Чтобы избежать этого, предлагаю следующий трюк. Потребуется чуть больше кода, но теперь даже IDE не сможет подсовывать это поле в подсказках.
Для каждого » super private » поля нам потребуется интерфейс расширяющий Supplier и Consumer и объект анонимного класса, реализующего этот интерфейс, в который мы помещаем поле value. Вся логика геттера и сеттера происходит в этом классе. Сами геттер и сеттер — лишь обёртки для public доступа.
Всё понятно из примера ниже.
import java.util.function.Consumer; import java.util.function.Supplier; /** * Пример использования "super private" поля value, доступ к которому * возможен только через геттер и сеттер даже из методов самого класса */ public class GetterSetter < interface SupplierConsumerextends Supplier, Consumer <> /** * объект анонимного класса имплементирущего SupplierConsumer, * содержащий поле value. * Используется в обёртке сеттера setValue(. ) и геттера getValue() */ private final SupplierConsumer get_set_value = new SupplierConsumer<>() < /** * Само поле value */ String value; /** * Реализация интерфейса Supplier * @return - значение поля value */ @Override public String get() < return value; >/** * Реализация интерфейса Consumer * @param another_value - новое значение для поля value */ @Override public void accept(String another_value) < /* Здесь можно выполнить нужные проверки и другие действия */ value = another_value; >>; /** * Геттер для поля value * @return значение поля value */ public String getValue() < return get_set_value.get(); >/** * Сеттер для поля value * @param value - новое значение для поля value */ public void setValue(String value) < get_set_value.accept(value); >static public void main(String[] args) < GetterSetter gs = new GetterSetter(); System.out.println(gs.getValue()); gs.setValue("Здравствуй, мир!"); System.out.println(gs.getValue()); >>
Запуск класса выводит, как и ожидалось:
"java.exe" GetterSetter null Здравствуй, мир!
Не могу получить значение скрытого поля

Добрый день.
Делаю портлет для Liferay с веб-формой для передачи данных стороннему веб-сервису.
В файле jsp с помощью ajax заполняю таблицу, добавляя в нее input type=hidden name=competition. Все успешно добавляется.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
var addMyCompetition = function (id, programId) { var added = false; var addedProg = false; var programs = {}; var comps = $('#myCompetitions'); comps.find('.competition').each(function () { var o = $(this); if (!added && o.val() == id) { added = true; } }); comps.find('.programId').each(function () { var o = $(this); if (o.val() == programId) { addedProg = true; } }); if (programId !== undefined) { comps.find('.programId').each(function () { var o = $(this).val(); programs[o] = o; }); } console.log(programs); if ((!added && Object.keys(programs).length 2) || (addedProg && !added)) { $.ajax({ url : "", type : 'POST', dataType : 'json', data : { competitionId : id }, success : function(data) { console.log(JSON.stringify(data)); for(var i in data) { var myCompetitions = $('#myCompetitions'); myCompetitions.append('competition" value="'+ data[i].competitionId +'" />'); } }, error : function() { console.log("There was an error. Try again please!"); } }); } };
В классе-обработчике пытаюсь получить значения value сгенерированных input, с помощью ParamUtil.getParameterValues, но они не приходят(
1 2 3 4 5 6
_log.info("competitionArray"+Arrays.toString(ParamUtil.getParameterValues(request, "competition"))); String[] competitions = ParamUtil.getParameterValues(request, "competition", new String[0]); for (int i = 0; i competitions.length; i++) { _log.info("competition="+competitions[i]); }
Данные из всех остальных полей формы успешно приходят. Пробовала добавить в jsp input (
В чем проблема? Почему не могу получить value созданных с помощью ajax input-полей?
Заранее спасибо!
Скрыть поле запроса в Swagger API
Мы можем использовать Swagger UI в качестве платформы для удобной визуализации интерфейсов API и взаимодействия с ними. Это мощный инструмент для создания структур API с минимальной необходимой настройкой.
В этой статье мы сосредоточимся на использовании Swagger с API REST Spring Boot . В частности, мы рассмотрим различные способы скрытия поля запроса в пользовательском интерфейсе Swagger.
2. Введение
Для простоты мы создадим базовое приложение Spring Boot и изучим API с помощью пользовательского интерфейса Swagger.
Давайте создадим простое приложение ArticleApplication , используя Spring Boot. Мы предоставляем два API с помощью ArticlesController . Используя GET API, мы хотим получить подробную информацию обо всех статьях.
С другой стороны, мы используем POST API для добавления деталей для новой статьи:
@RestController @RequestMapping("/articles") public class ArticlesController @Autowired private ArticleService articleService; @GetMapping("") public ListArticle> getAllArticles() return articleService.getAllArticles(); > @PostMapping("") public void addArticle(@RequestBody Article article) articleService.addArticle(article); > >
Мы будем использовать класс Article в качестве объекта передачи данных (DTO) для этих API. Теперь добавим несколько полей в класс Article :
public class Article private int id; private String title; private int numOfWords; // standard getters and setters >
Мы можем получить доступ к пользовательскому интерфейсу Swagger по адресу http://localhost:8080/swagger-ui/#/articles-controller . Давайте запустим приложение и посмотрим на поведение по умолчанию для двух вышеуказанных API:


В POST API мы принимаем все данные, а именно id , title и numOfWords , от пользователя. В GET API мы возвращаем те же поля в ответе. Мы видим, что по умолчанию Swagger показывает все поля для обоих API.
Теперь предположим, что мы хотим использовать отдельную внутреннюю логику для установки поля id . В таком сценарии мы не хотим, чтобы пользователь вводил информацию, связанную с полем id . Чтобы избежать путаницы, мы хотим скрыть это поле в пользовательском интерфейсе Swagger.
Ближайший вариант, который приходит в голову, — это создание отдельного DTO и скрытие в нем нужных полей. Этот метод может быть полезен, если мы хотим добавить дополнительную логику для DTO. Мы можем использовать этот вариант, если он соответствует нашим общим требованиям.
В этой статье давайте используем различные аннотации, чтобы скрыть поля в пользовательском интерфейсе Swagger.
3. Использование @JsonIgnore
@JsonIgnore — это стандартная аннотация Джексона . Мы можем использовать его, чтобы указать, что поле должно игнорироваться Джексоном во время сериализации и десериализации . Мы можем добавить аннотацию только к полю, которое будет игнорироваться, и она скроет как геттеры, так и сеттеры для указанного поля.
@JsonIgnore private int id;
Давайте перезапустим приложение и изучим пользовательский интерфейс Swagger:


Мы видим, что теперь поле id не отображается в описаниях API. Swagger также предоставляет аннотации для достижения аналогичного поведения.
4. Использование @ApiModelProperty
@ApiModelProperty предоставляет метаданные, относящиеся к свойствам объекта модели . Мы можем использовать скрытое свойство аннотации, чтобы скрыть поле в определении объекта модели в пользовательском интерфейсе Swagger.
Давайте попробуем это для поля id :
@ApiModelProperty(hidden = true) private int id;
В приведенных выше сценариях мы обнаруживаем, что поле id скрыто как для GET , так и для POST API. Предположим, мы хотим разрешить пользователям просматривать сведения об идентификаторе как часть ответа GET API. В этом случае нужно искать другие варианты.
Swagger также предоставляет альтернативное свойство readOnly . Мы можем использовать его, чтобы скрыть указанное поле во время операций обновления, но по-прежнему отображать его для операций извлечения .
Давайте рассмотрим это:
@ApiModelProperty(readOnly = true) private int id;
Теперь давайте проверим обновленный пользовательский интерфейс Swagger:


Мы видим, что поле id теперь видимо для GET API, но остается скрытым для POST API — оно поддерживает операции только для чтения .
Это свойство помечено как устаревшее, начиная с версии 1.5.19 . Для более высоких версий давайте рассмотрим другие аннотации.
5. Использование @JsonProperty
Джексон предоставляет аннотацию @JsonProperty . Мы можем использовать его для добавления ` метаданных, связанных с геттерами/сеттерами поля POJO, которые можно использовать во время сериализации/десериализации объектов. Мы можем **установить свойство доступа аннотации, чтобы разрешить только операции чтения` ** в определенном поле:
@JsonProperty(access = JsonProperty.Access.READ_ONLY) private int id;
Таким образом, мы можем скрыть поле id для определения модели POST API, но по-прежнему можем отображать его в ответе GET API.
Давайте рассмотрим другой способ достижения желаемой функциональности.
6. Использование @ApiParam
@ApiParam также является аннотацией Swagger, которую мы можем использовать для указания метаданных, связанных с параметрами запроса. Мы можем установить для скрытого свойства значение true , чтобы скрыть любое свойство. Однако здесь у нас есть ограничение: это работает, только если мы используем @ModelAttribute вместо @RequestBody для доступа к данным запроса.
@PostMapping("") public void addArticle(@ModelAttribute Article article) articleService.addArticle(article); >
@ApiParam(hidden = true) private int id;
Давайте рассмотрим спецификации пользовательского интерфейса Swagger для этого случая:

Нам удалось скрыть поле id в определении данных запроса POST API.
7. Заключение
Мы рассмотрели различные варианты изменения видимости свойств объекта модели в пользовательском интерфейсе Swagger. Обсуждаемые аннотации также предлагают несколько других функций, которые мы можем использовать для обновления спецификаций Swagger. Мы должны использовать соответствующие методы в соответствии с нашими требованиями.
Исходный код доступен на GitHub .
- 1. Обзор
- 2. Введение
- 3. Использование @JsonIgnore
- 4. Использование @ApiModelProperty
- 5. Использование @JsonProperty
- 6. Использование @ApiParam
- 7. Заключение
Spring MVC – пример скрытого поля
В следующем примере описывается использование скрытого поля в формах с использованием среды Spring Web MVC. Для начала давайте наладим работающую среду Eclipse IDE и рассмотрим следующие шаги для разработки веб-приложения на основе динамических форм с использованием Spring Web Framework.
| шаг | Описание |
|---|---|
| 1 | Создайте проект с именем HelloWeb в пакете com.tutorialspoint, как описано в главе Spring MVC – Hello World. |
| 2 | Создайте классы Java Student, StudentController в пакете com.tutorialspoint. |
| 3 | Создайте файлы представлений student.jsp, result.jsp в подпапке jsp. |
| 4 | Последний шаг – создание содержимого исходного файла и файлов конфигурации и экспорт приложения, как описано ниже. |
Student.java
package com.tutorialspoint; public class Student private Integer age; private String name; private Integer id; public void setAge(Integer age) this.age = age; > public Integer getAge() return age; > public void setName(String name) this.name = name; > public String getName() return name; > public void setId(Integer id) this.id = id; > public Integer getId() return id; > >
StudentController.java
package com.tutorialspoint; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import org.springframework.ui.ModelMap; @Controller public class StudentController @RequestMapping(value = "/student", method = RequestMethod.GET) public ModelAndView student() return new ModelAndView("student", "command", new Student()); > @RequestMapping(value = "/addStudent", method = RequestMethod.POST) public String addStudent(@ModelAttribute("SpringWeb")Student student, ModelMap model) model.addAttribute("name", student.getName()); model.addAttribute("age", student.getAge()); model.addAttribute("id", student.getId()); return "result"; > >
Здесь для первого сервисного метода student () мы передали пустой объект Studentobject в объекте ModelAndView с именем «command», потому что среда Spring ожидает объект с именем «command», если вы используете теги в вашем файле JSP. Таким образом, когда вызывается метод student () , он возвращает представление student.jsp .
Второй сервисный метод addStudent () будет вызываться для метода POST по URL-адресу HelloWeb / addStudent . Вы подготовите свой модельный объект на основе предоставленной информации. Наконец, из метода сервиса будет возвращено представление «result», что приведет к отображению result.jsp
student.jsp
@taglib uri = "http://www.springframework.org/tags/form" prefix = "form"%> Spring MVC Form Handling Student Information method = "POST" action = "/HelloWeb/addStudent">path = "name">Name path = "name" /> path = "age">Age path = "age" /> path = "id" value = "1" /> colspan = "2"> type = "submit" value = "Submit"/>
Здесь мы используем тег для визуализации скрытого HTML-поля.
Он будет отображать следующий HTML-контент.
result.jsp
Spring MVC Form Handling Submitted Student Information
| Name | $ |
| Age | $ |
| ID | $ |
Когда вы закончите создавать исходные файлы и файлы конфигурации, экспортируйте ваше приложение. Щелкните правой кнопкой мыши свое приложение и используйте опцию Экспорт → Файл WAR и сохраните файл HelloWeb.war в папке веб-приложений Tomcat.
Теперь запустите сервер Tomcat и убедитесь, что вы можете получить доступ к другим веб-страницам из папки webapps с помощью стандартного браузера. Попробуйте URL – http: // localhost: 8080 / HelloWeb / student, и мы увидим следующий экран, если все в порядке с веб-приложением Spring.

После отправки необходимой информации, нажмите на кнопку отправки, чтобы отправить форму. Мы увидим следующий экран, если все в порядке с вашим веб-приложением Spring.