<td th:text="${user.name}" ng-show="shouldShowUsername()">Username</td>
th:removetag
, но тоже не всегда. В одном из случаев мы пытались генерировать блок стилей в head страницы и у Thymeleaf, насколько я помню, были проблемы с этим (возможно, починили).import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class ChatServer {
public static void main(String[] args) throws IOException {
try (ServerSocket serverSocket = new ServerSocket(5000)) {
while (true) {
Socket clientSocket = serverSocket.accept();
System.out.println("New connection: " + clientSocket.getRemoteSocketAddress().toString());
ClientThread clientThread = new ClientThread(clientSocket);
clientThread.start();
}
}
}
private static class ClientThread extends Thread {
private final Socket socket;
private ClientThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
String request;
while ((request = in.readLine()) != null) {
System.out.println("New message from " + socket.getRemoteSocketAddress().toString() + ": " + request);
StringBuilder sb = new StringBuilder(request);
String response = sb.reverse().toString();
out.println(response);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("Closing connection: " + socket.getRemoteSocketAddress().toString());
try {
socket.close();
} catch (IOException ignored) {}
}
}
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class ChatClient implements Runnable, ActionListener, OnMessageListener {
private JTextArea messageArea;
private JTextField messageField;
private WorkerThread workerThread;
public static void main(String[] args) {
ChatClient client = new ChatClient();
client.run();
}
private ChatClient() {
initGui();
initListeners();
}
private void initGui() {
JFrame frame = new JFrame();
JButton sendButton = new JButton("Send");
sendButton.addActionListener(this);
messageArea = new JTextArea(10, 10);
messageField = new JTextField(20);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.add(messageArea);
mainPanel.add(messageField);
mainPanel.add(sendButton);
frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setVisible(true);
}
private void initListeners() {
Observer.getInstance().addListener(this);
}
@Override
public void run() {
try {
workerThread = new WorkerThread("127.0.0.1", 5000);
workerThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void actionPerformed(ActionEvent e) {
if (workerThread == null) {
return;
}
String request = messageField.getText();
messageField.setText("");
workerThread.sendMessage(request);
}
@Override
public void onMessage(String message) {
messageArea.append(message + System.lineSeparator());
}
private static class WorkerThread extends Thread {
private final Socket socket;
private final PrintWriter out;
private WorkerThread(String host, int port) throws IOException {
this.socket = new Socket(host, port);
this.out = new PrintWriter(socket.getOutputStream(), true);
System.out.println("Connection established...");
}
@Override
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String message;
while ((message = in.readLine()) != null) {
System.out.println("New message: " + message);
Observer.getInstance().fireEvent(message);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("Connection closing...");
try {
out.close();
socket.close();
} catch (Exception ignored) {}
}
}
public synchronized void sendMessage(String message) {
out.println(message);
}
}
}
public class Observer {
private static final Observer INSTANCE = new Observer();
public static Observer getInstance() {
return INSTANCE;
}
private final Set<OnMessageListener> listeners;
private Observer() {
listeners = Collections.synchronizedSet(new HashSet<>());
}
public void addListener(OnMessageListener listener) {
this.listeners.add(listener);
}
synchronized void fireEvent(String message) {
for (OnMessageListener listener : listeners) {
listener.onMessage(message);
}
}
}
public interface OnMessageListener {
void onMessage(String message);
}
В реальной жизни самое главное отличие между ними с точки зрения производительности заключается в том, что поток выполнения использует одну и ту же область памяти, а процессы получают собственные области. Поэтому отдельные процессы требуют гораздо больше памяти.
<a href="/file/123.html" download>Download</a>
Content-Disposition: attachment; filename=123.html
@Entity
@Table(name = "students")
@Data
public class Student extends BaseModel {
@Id
private Long id;
@Column
private Long studentId;
@Column
private String firstname;
@Column
private String lastname;
}
...
public Student add(Student student) {
Session session = sessionFactory.getCurrentSession();
student.setId(null); // добавить новую запись, а не изменить существующую
session.save(student);
return student;
}
...