public void sendCommentToAllClients(Comment comment) {
if (ns != null) {
ns.broadcast("comment:save", comment);
}
}
@PostMapping("/add-comment")
public ResponseEntity<Comment> addComment(@RequestBody BookResponse reqBody, Authentication authentication) {
try {
// (...)
commentRepository.save(comment);
// Отправляем комментарий всем подключенным клиентам
socketEmitter.sendCommentToAllClients(comment);
return ResponseEntity.status(HttpStatus.OK).body(comment);
} catch (Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.build();
}
}
useEffect(() => {
socket.on('comment:save', (data: Comment) => {
const comment = JSON.parse(data as any)
console.log('comment', comment);
props.book.comments.push(comment);
// Если setBookInState обновляет состояние, это может быть полезно для перерисовки
// props.setBookInState({...props.book});
toast.info('Got event from socket: Book ' + comment.text)
});
}, [socket]);
version: '3.7'
services:
app:
build: ${PWD}/fpm/
image: cubinez85/docker_compose/app:latest
container_name: app
volumes:
- ${PWD}/code:/data
networks:
- app-network
webserver:
build: ${PWD}/nginx/
image: cubinez85/docker_compose/nginx:latest
container_name: webserver
volumes:
- ${PWD}/code:/data
ports:
- "80:80"
- "443:443"
networks:
- app-network
db:
image: mysql:latest
container_name: db
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
volumes:
- ${PWD}/dbdata:/var/lib/mysql
networks:
- app-network
networks:
app-network:
driver: bridge
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
...
}
<Switch>
внутри модалки:<Modal>
<Switch>
<Route path="/modal/presets" component={Presets} />
<Route path="/modal/edit/:id" component={EditPhrase} />
<Route path="/modal/create" component={CreatePhrase} />
<Route path="/modal/delete/:id" component={DeletePhrase} />
{/* ... */}
</Switch>
</Modal>
function ModalComponent() {
return (
<Modal>
<Switch>
<Route path="/modal/presets" component={Presets} />
<Route path="/modal/edit/:id" component={EditPhrase} />
<Route path="/modal/create" component={CreatePhrase} />
<Route path="/modal/delete/:id" component={DeletePhrase} />
{/* ... */}
</Switch>
</Modal>
);
}
function Presets() {
const phrases = ... // получите фразы
return (
<div>
{phrases.map(phrase => (
<div key={phrase.id}>
{phrase.text}
<Link to={`/modal/edit/${phrase.id}`}>Редактировать</Link>
</div>
))}
<Link to="/modal/create">Создать новую фразу</Link>
</div>
);
}
<input>
, значение этого поля не отправляется на сервер вместе с другими данными формы. Таким образом, при отправке формы, поля с атрибутом disabled будут игнорироваться.*{settings[__${item.index}__].name}
установлено как disabled, и поэтому name всегда будет null при обработке POST-запроса на сервере.<td>
<input disabled th:value="*{settings[__${item.index}__].name}">
<input type="hidden" th:field="*{settings[__${item.index}__].name}">
</td>
Scanner input = new Scanner(System.in);
String[] list = new String[4];
System.out.println("Insert list elements: ");
for (int i = 0; i < list.length; i++) {
list[i] = input.nextLine();
}
System.out.print("Inserted list elements: ");
for (String s : list) {
System.out.print(" " + s);
}
System.out.print("Ввод нужного адреса: ");
String address = input.nextLine();
long count = IntStream.range(0, list.length).filter(i -> address.equals(list[i])).count();
System.out.println(count);
str
представляет собой неизменяемую последовательность байтов UTF-8 динамической длины где-то в памяти. Поскольку размер неизвестен, его можно обрабатывать только за указателем. Это означает, что str
чаще всего используется как &str
— ссылка на некоторые данные UTF-8, обычно называемые «срезом строки» или просто «срезом». Срез — это просто представление данных, и эти данные могут быть где угодно, например:&'static str.
Данные жестко закодированы в исполняемый файл и загружаются в память при запуске программы.use std::str;
let x: &[u8] = &[b'a', b'b', b'c'];
let stack_str: &str = str::from_utf8(x).unwrap();
String
, если вам требуется владение строковыми данными (например, передача строк в другие потоки или их создание во время выполнения), и используйте &str
, если вам нужно только представление строки. Pattern p = Pattern.compile("[0-9]+");
Matcher m = p.matcher("string1234(((more56))7))string890");
while (m.find()) {
System.out.println(m.group()); //1234 56 7 890
}
git checkout <your_commit_sha>
git checkout -b old-state <your_commit_sha>
checkout
ветку, в которой вы были. (Если вы внесли изменения, при переключении веток, вам придется обращаться с ними соответствующим образом.# Это создаст три отдельных коммита возврата:
git revert <your_commit_sha1> < your_commit_sha2> <your_commit_sha3>
# Это вернет последние два коммита. Также принимает диапазоны:
git revert HEAD~2..HEAD
# Точно так же вы можете отменить ряд коммитов, используя хэши коммитов (не включая первый хеш):
git revert <your_commite_sha>
# Отмена мердж коммита:
git revert -m 1 <merge_commit_sha>
# Чтобы получить только один коммит, вы можете использовать 'rebase -i',
# Или вы можете сделать это вручную (обязательно сделайте это на верхнем уровне вашего репозитория)
# Привести ваш индекс и дерево в нужное состояние, не меняя HEAD:
git checkout <your_target_commit_sha>
# После чего обязательно зафиксируйте коммит. Будьте уверены в том, что вы сделали на 150% и напишите хорошее сообщение с описанием того, что вы только что сделали:
git commit
%1$s
и использовать String.format
для замены плейсхолдеров на фактическую строку, которую вам нужно использовать.public class Main {
public static final String DELIMITER = "((?<=%1$s)|(?=%1$s))";
public static void main(String[] args) {
String task = "Заменить, в тексте все! слова длиной? не больше 6 символов; в обратном порядке начинающиеся на: согласную букву ";
String[] arr = task.split(String.format(DELIMITER, "[:?;!. ]"));
String result = Arrays.stream(arr)
.map(s -> !check(s.charAt(0)) && !length(s) ? reverse(s) : s)
.collect(Collectors.joining());
System.out.println(result); /* Заменить, в етскет есв! аволс йонилд? ен ешьлоб 6 символов; в обратном порядке начинающиеся ан: согласную увкуб */
}
public static boolean check(char c) {
return "аиеёоуыэюя".indexOf(c) > -1;
}
public static boolean length(String s) {
return s.length() > 6;
}
public static String reverse(String s) {
return new StringBuilder(s).reverse().toString();
}
}
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
getPrincipal()
getCredentials()
getAuthorities()
getDetails()
public String foo(Model model) {
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = user.getUsername();
model.addAttribute("username", username);
return "your_view";
}
<td th:each="user : ${user}">
<a th:if="${username == user.username}" th:href="@{/profile/{id}(id=${user.id}}">Profile</a>
</td>
public static void main(String[] args) {
int[] array = {1, 2, 3, 4, 5};
int[] result = IntStream.rangeClosed(1, array.length)
.map(i -> array[array.length - i])
.toArray();
System.out.println(Arrays.toString(result));
}
public static void main(String[] args) {
Integer[] array = {1, 2, 3, 4, 5};
List<Integer> list = Arrays.asList(array);
Collections.reverse(list);
System.out.println(Arrays.toString(list.toArray()));
}
public static void main(String[] args) {
int[] array = {1, 2, 3, 4, 5};
for (int i = 0; i < array.length / 2; i++) {
int tmp = array[i];
array[i] = array[array.length - 1 - i];
array[array.length - 1 - i] = tmp;
}
}
Зачем считывать файл через Scanner?
Зачем использовать цикл? нельзя взять и всю прочитать без цикла?
Зачем строке происваевать данные файла?
fromJson
мы сохраняем прочитанные данные, а поскольку JSON представляет собой обычный набор текста, то использование типа String более чем подходит для этой операции. Вы также можете использовать коллекции или массивы для этого.Зачем указывать тип объекта в конце?
fromJson
десериализует JSON, прочитанный из Reader'а (в данном случае из строки) в объект класса, указанного вторым аргументом.