Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
HBox. В качестве атрибутов xmlns указаны пространства имен для тэгов FXML. Все остальные элементы размещаются внутри HBox, что в точности соответствует структуре дерева;public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="sample.Sample"
prefHeight="400.0" prefWidth="600.0">
</AnchorPane><?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<HBox xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
prefHeight="400.0" prefWidth="600.0">
<children>
<Button text="Кнопка"/>
<VBox prefHeight="200.0" prefWidth="100.0">
<children>
<Label text="Текст"/>
</children>
</VBox>
</children>
</HBox>@Override
public void start(Stage primaryStage) throws Exception {
HBox hBox = new HBox();
hBox.setPrefHeight(400);
hBox.setPrefWidth(600);
Button button = new Button("Кнопка");
Label label = new Label("Текст");
VBox vBox = new VBox();
vBox.setPrefHeight(200);
vBox.setPrefWidth(100);
vBox.getChildren().add(label);
hBox.getChildren().addAll(button,vBox);
Scene scene = new Scene(hBox, 300, 200);
primaryStage.setTitle("JavaFX-приложение");
primaryStage.setScene(scene);
primaryStage.show();
}<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<!-- xmlns="http://javafx.com/javafx"-->
<!-- xmlns:fx="http://javafx.com/fxml"-->
<GridPane fx:controller="sample.SampleController" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.1" xmlns:fx="http://javafx.com/fxml/1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" text="Кнопка 1" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
<font>
<Font size="22.0" />
</font>
<GridPane.margin>
<Insets />
</GridPane.margin>
</Button>
<Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Кнопка 2" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
<font>
<Font size="22.0" />
</font>
</Button>
<Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Кнопка 3" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
<font>
<Font size="22.0" />
</font>
</Button>
<Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Кнопка 4" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
<font>
<Font size="22.0" />
</font>
</Button>
<Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Кнопка 5" GridPane.hgrow="ALWAYS" GridPane.rowIndex="2" GridPane.vgrow="ALWAYS">
<font>
<Font size="22.0" />
</font>
</Button>
<Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Кнопка 6" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.rowIndex="2" GridPane.vgrow="ALWAYS">
<font>
<Font size="22.0" />
</font>
</Button>
</children>
</GridPane>
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Parent root =
FXMLLoader.load(getClass().getResource("sample.fxml"));
Scene scene = new Scene(root, 300, 200);
primaryStage.setTitle("JavaFX-приложение");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}public class SampleController implements Initializable {
@Override
public void initialize(URL location, ResourceBundle resources) {
}
}public class SampleController implements Initializable {
@FXML
private Button button1;
@FXML
private Button button2;
@Override
public void initialize(URL location, ResourceBundle resources) {
}
}public class SampleController implements Initializable {
@FXML
private Button button1;
@FXML
private Button button2;
@Override
public void initialize(URL location, ResourceBundle resources) {
button1.setOnAction(event -> {
new Alert(Alert.AlertType.CONFIRMATION,"Вы нажали кнопку 1").showAndWait();
});
}
}public class SampleController implements Initializable {
@FXML
private Button button1;
@FXML
private Button button2;
@FXML
protected void handleButton2(ActionEvent event) {
new Alert(Alert.AlertType.CONFIRMATION,"Вы нажали кнопку 2").showAndWait();
}
@Override
public void initialize(URL location, ResourceBundle resources) {
button1.setOnAction(event -> {
new Alert(Alert.AlertType.CONFIRMATION,"Вы нажали кнопку 1").showAndWait();
});
}
}public class Student {
private String firstName;
private String lastName;
private String group;
public Student(String firstName, String lastName, String group) {
this.firstName = firstName;
this.lastName = lastName;
this.group = group;
}
@Override
public String toString() {
return "Student{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", group='" + group + '\'' +
'}';
}
}
public class Controller implements Initializable {
@Override
public void initialize(URL location, ResourceBundle resources) {
}
@FXML
public void add(ActionEvent event) {
// Обработчик кнопки "Добавить"
}
@FXML
public void delete(ActionEvent event) {
// Обработчик кнопки "Удалить"
}
}public class Main extends Application {
private List<Student> list;
@Override
public void init() throws Exception {
list = new ArrayList<>();
}
public void addStudent(Student student) {
list.add(student);
}
public void deleteStudent(Student student) {
list.remove(student);
}
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}public class StudentFacade {
private List<Student> studentList;
public StudentFacade() {
studentList = new ArrayList<>();
}
public void addStudent(Student student) {
studentList.add(student);
}
public void deleteStudent(Student student) {
studentList.remove(student);
}
}public class Main extends Application {
private StudentFacade facade;
@Override
public void init() throws Exception {
facade = new StudentFacade();
}
public void addStudent(Student student) {
facade.addStudent(student);
}
public void deleteStudent(Student student) {
facade.deleteStudent(student);
}
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
} @Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("../view/sample.fxml"));
Parent root = loader.load();
primaryStage.setTitle("Студенты");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}public class Controller implements Initializable {
private Main main;
public void getMainController(Main main) {
this.main = main;
}
...
} @Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("../view/sample.fxml"));
Parent root = loader.load();
Controller controller = loader.getController();
controller.getMainController(this);
primaryStage.setTitle("Студенты");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
} @FXML
public void add(ActionEvent event) {
// Создаем объект студента
Student student = new Student(
String.valueOf(new Random().nextInt(100)),
String.valueOf(new Random().nextInt(100)),
String.valueOf(new Random().nextInt(100))
);
// Вызываем метод добавления студента
main.addStudent(student);
}public class StudentFacade extends Observable {
private List<Student> studentList;
public StudentFacade() {
studentList = new ArrayList<>();
}
public void addStudent(Student student) {
studentList.add(student);
setChanged();
notifyObservers(studentList);
}
public void deleteStudent(Student student) {
studentList.remove(student);
setChanged();
notifyObservers(studentList);
}
}public class ListViewObserver extends ListView<Student> implements Observer {
@Override
public void update(Observable o, Object arg) {
if (o instanceof StudentFacade) {
// В параметре arg передан список для отображения
List<Student> list = (List<Student>) arg;
getItems().clear();
getItems().addAll(list);
}
}
} public void bindObserverToFacade(Observer o) {
facade.addObserver(o);
}public class Controller implements Initializable {
private Main main;
@FXML
private ListViewObserver list;
public void getMainController(Main main) {
this.main = main;
main.bindObserverToFacade(list);
}
...
}









HttpServletResponseHttpServletRequestHttpServletResponseContent-Dispositiontext/plain@RestController
public class HelloController {}@RestController
public class HelloController {
public String hello() {
return "hello";
}
}@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
}@GetMapping("/room/{id}")
public void getRoomById() {
}@GetMapping("/room/{id}")
public void getRoomById(@PathVariable(value = "id") int roomId) {
// ...
}@GetMapping("/room/{id1}/{id2}")
public void getRoomById(@PathVariable(value = "id1") int blockId, @PathVariable(value = "id2") int roomId) {
// ...
}// запрос: http://localhost:8080/room?room_id=250&block_id=10
@GetMapping("/room")
public void getRoomById(@RequestParam(value = "room_id") int roomId, @RequestParam(value = "block_id") int blockId) {
// ...
}@PostMapping("/book")
public void bookRoom(@RequestParam(value = "room_id") int room_id,
@RequestParam(value = "firstname") String firstname,
@RequestParam(value = "lastname") String lastname,
@RequestParam(value = "days") int days) {
// ...
} @GetMapping("/roominfo")
public Room getRoomInfoById(@RequestParam(value = "room_id") int roomId) {
return new Room(roomId, "Отличная комната!", 2, 200);
}public class Room {
private Integer id;
private String roomInfo;
private Integer roomCapacity;
private double price;
public Room(Integer id, String roomInfo, Integer roomCapacity, double price) {
this.id = id;
this.roomInfo = roomInfo;
this.roomCapacity = roomCapacity;
this.price = price;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getRoomInfo() {
return roomInfo;
}
public void setRoomInfo(String roomInfo) {
this.roomInfo = roomInfo;
}
public Integer getRoomCapacity() {
return roomCapacity;
}
public void setRoomCapacity(Integer roomCapacity) {
this.roomCapacity = roomCapacity;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}public class Student {
private String firstname;
private String lastname;
private String phone;
private int age;
public Student(String firstname, String lastname, String phone, int age) {
this.firstname = firstname;
this.lastname = lastname;
this.phone = phone;
this.age = age;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"firstname='" + firstname + '\'' +
", lastname='" + lastname + '\'' +
", phone='" + phone + '\'' +
", age=" + age +
'}';
}
}@PostMapping("/student")
public void addStudent(@RequestBody Student student) {
System.out.println(student);
}@GetMapping("/student")
public ResponseEntity<?> getStudentById(@RequestParam(value = "id") int studentId) {
if (studentId < 1) {
return ResponseEntity.badRequest().body("Invalid id");
} else {
return ResponseEntity.ok(new Student("Ivan", "Ivanov", "223322", 20));
}
}public class User {
public void sendMessage(String message, String target) {
Sender sender = new Sender();
sender.send(message, target);
}
}
public class Sender {
public void send(String message, String target) {
System.out.println("Tweet: " + message + " to " + target);
}
}








XmlWebApplicationContext – загружает определение контекста из XML-файла, содержащегося внутри веб-приложения.











<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" xmlns:th="http://www.thymeleaf.org">
<title>Index page</title>
</head>
<body>
<h1>Hello, world!</h1>
</body>
</html><!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body class="bg-light">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">Электронный деканат</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExample05"
aria-controls="navbarsExample05" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarsExample05">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="#">Главная</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="#">Студенты <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Группы</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Кафедры</a>
</li>
</ul>
<form class="form-inline mt-2 mt-md-0">
<input class="form-control mr-sm-2" type="text" placeholder="Введите текст" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Поиск</button>
</form>
</div>
</nav>
<div class="container">
<div class="py-5 text-center">
<h2>Управление студентами</h2>
<p class="lead">На данной странице вы можете добавить, отредактировать поля или удалить студентов кафедры</p>
</div>
<div class="row">
<div class="col">
<h2>Группа АИ-171</h2>
</div>
<div class="col col-lg-3">
<a th:href="@{~/add_student}" class="btn btn-lg btn-block btn-outline-primary" role="button"
aria-disabled="true">Добавить студента</a>
</div>
</div>
<br/>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th class="text-justify">#</th>
<th class="text-justify">Фамилия</th>
<th class="text-justify">Имя</th>
<th class="text-justify">Отчество</th>
<th class="text-justify">Почта</th>
<th class="text-justify">Телефон</th>
<th class="text-justify">Адрес</th>
</tr>
</thead>
<tbody>
<tr th:each="student : ${students}">
<td class="align-middle"><span th:text="${student.id}"/></td>
<td class="align-middle"><span th:text="${student.lastName}"/></td>
<td class="align-middle"><span th:text="${student.firstName}"/></td>
<td class="align-middle"><span th:text="${student.patronymic}"/></td>
<td class="align-middle"><span th:text="${student.email}"/></td>
<td class="align-middle"><span th:text="${student.phone}"/></td>
<td class="align-middle"><span th:text="${student.address}"/></td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
</body>
</html><!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<title>Добавление студента</title>
</head>
<body class="bg-light">
<div class="container">
<div class="py-5 text-center">
<h2>Добавление студента</h2>
<p class="lead">Заполните поля и нажмите кнопку 'Добавить студента'</p>
</div>
<form method="post" class="needs-validation" novalidate>
<div class="row">
<div class="col-md-12">
<h4 class="mb-3">Поля для заполнения</h4>
<div class="row">
<div class="col-md-4 mb-3">
<label for="lastName">Фамилия</label>
<input type="text" class="form-control" id="lastName" placeholder=""
value="" required>
</div>
<div class="col-md-4 mb-3">
<label for="firstName">Имя</label>
<input type="text" class="form-control" id="firstName" placeholder=""
value="" required>
</div>
<div class="col-md-4 mb-3">
<label for="patronymic">Отчество</label>
<input type="text" class="form-control" id="patronymic" placeholder=""
value="" required>
</div>
</div>
<div class="mb-3">
<label for="email">Электронная почта</label>
<input type="email" class="form-control" id="email"
placeholder="" value="" required>
</div>
<div class="mb-3">
<label for="phone">Телефон</label>
<input type="text" class="form-control" id="phone"
placeholder="(ХХХ) ХХХ-ХХХХ" value="" required>
</div>
<div class="mb-3">
<label for="address">Домашний адрес</label>
<input type="text" class="form-control" id="address" placeholder="" value=""
required>
</div>
<hr class="mb-4">
<button class="btn btn-primary btn-lg btn-block" type="submit" value="Submit">Добавить студента</button>
</form>
</div>
</div>
</div>
<br/><br/><br/>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
</body>
</html>@Controller
public class StudentController {
@GetMapping("/")
public String index(Model model) {
return "index";
}
@GetMapping("/add_student")
public String addStudent(Model model) {
return "add_student";
}
} <div class="col col-lg-3">
<a th:href="@{~/add_student}" class="btn btn-lg btn-block btn-outline-primary" role="button"
aria-disabled="true">Добавить студента</a>
</div>public class Student {
private long id;
private String lastName;
private String firstName;
private String patronymic;
private String email;
private String phone;
private String address;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getPatronymic() {
return patronymic;
}
public void setPatronymic(String patronymic) {
this.patronymic = patronymic;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Student() {}
public Student(String lastName, String firstName, String patronymic, String email, String phone, String address) {
this.lastName = lastName;
this.firstName = firstName;
this.patronymic = patronymic;
this.email = email;
this.phone = phone;
this.address = address;
}
}@Controller
public class StudentController {
...
@GetMapping("/add_student")
public String addStudent(Model model) {
model.addAttribute("student", new Student());
return "add_student";
}
}<form enctype="multipart/form-data" action="#" th:action="@{/add_student}" th:object="${student}" method="post" class="needs-validation"
novalidate>
<div class="row">
<div class="col-md-12">
<h4 class="mb-3">Поля для заполнения</h4>
<div class="row">
<div class="col-md-4 mb-3">
<label for="lastName">Фамилия</label>
<input th:field="*{lastName}" type="text" class="form-control" id="lastName" placeholder=""
value="" required>
</div>
<div class="col-md-4 mb-3">
<label for="firstName">Имя</label>
<input th:field="*{firstName}" type="text" class="form-control" id="firstName" placeholder=""
value="" required>
</div>
<div class="col-md-4 mb-3">
<label for="patronymic">Отчество</label>
<input th:field="*{patronymic}" type="text" class="form-control" id="patronymic" placeholder=""
value="" required>
</div>
</div>
<div class="mb-3">
<label for="email">Электронная почта</label>
<input th:field="*{email}" type="email" class="form-control" id="email"
placeholder="" value="" required>
</div>
<div class="mb-3">
<label for="phone">Телефон</label>
<input th:field="*{phone}" type="text" class="form-control" id="phone"
placeholder="(ХХХ) ХХХ-ХХХХ" value="" required>
</div>
<div class="mb-3">
<label for="address">Домашний адрес</label>
<input th:field="*{address}" type="text" class="form-control" id="address" placeholder="" value=""
required>
</div>
<hr class="mb-4">
<button class="btn btn-primary btn-lg btn-block" type="submit" value="Submit">Добавить студента</button>
</div>
</div>
</form>@Controller
public class StudentController {
...
@PostMapping("/add_student")
public String greetingSubmit(@ModelAttribute Student student) {
return "redirect:/";
}
}@Entity
@Table(name = "student")
public class Student {
@Id
@GeneratedValue
private long id;
private String lastName;
private String firstName;
private String patronymic;
private String email;
private String phone;
private String address;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getPatronymic() {
return patronymic;
}
public void setPatronymic(String patronymic) {
this.patronymic = patronymic;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Student() {
}
public Student(String lastName, String firstName, String patronymic, String email, String phone, String address) {
this.lastName = lastName;
this.firstName = firstName;
this.patronymic = patronymic;
this.email = email;
this.phone = phone;
this.address = address;
}
}public interface StudentRepository extends JpaRepository<Student,Long> {}@Service
public class StudentService {
private StudentRepository repository;
@Autowired
public void setRepository(StudentRepository repository) {
this.repository = repository;
}
public void saveStudent(Student student) {
repository.save(student);
}
}@Controller
public class StudentController {
private StudentService service;
@Autowired
public void setService(StudentService service) {
this.service = service;
}
...
@PostMapping("/add_student")
public String greetingSubmit(@ModelAttribute Student student) {
service.saveStudent(student);
return "redirect:/";
}
}@Controller
public class StudentController {
private StudentService service;
@Autowired
public void setService(StudentService service) {
this.service = service;
}
@GetMapping("/")
public String index(Model model) {
model.addAttribute("students", service.getAllStudents());
return "index";
}
...
}<table class="table table-striped">
<thead>
<tr>
<th class="text-justify">#</th>
<th class="text-justify">Фамилия</th>
<th class="text-justify">Имя</th>
<th class="text-justify">Отчество</th>
<th class="text-justify">Почта</th>
<th class="text-justify">Телефон</th>
<th class="text-justify">Адрес</th>
</tr>
</thead>
<tbody>
<tr th:each="student : ${students}">
<td class="align-middle"><span th:text="${student.id}"/></td>
<td class="align-middle"><span th:text="${student.lastName}"/></td>
<td class="align-middle"><span th:text="${student.firstName}"/></td>
<td class="align-middle"><span th:text="${student.patronymic}"/></td>
<td class="align-middle"><span th:text="${student.email}"/></td>
<td class="align-middle"><span th:text="${student.phone}"/></td>
<td class="align-middle"><span th:text="${student.address}"/></td>
</tr>
</tbody>
</table><form enctype="multipart/form-data" action="#" th:action="@{/}" th:object="${student}" method="post" class="needs-validation">
<div class="row">
<div class="col-md-12">
<h4 class="mb-3">Поля для заполнения</h4>
<div class="row">
<div class="col-md-6 mb-3">
<label for="lastName">Фамилия</label>
<input th:field="*{lastName}" type="text" class="form-control" id="lastName">
</div>
<div class="col-md-6 mb-3">
<label for="firstName">Имя</label>
<input th:field="*{firstName}" type="text" class="form-control" id="firstName">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="email">Электронная почта</label>
<input th:field="*{email}" type="text" class="form-control" id="email">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="age">Возраст</label>
<input th:field="*{age}" type="number" class="form-control" id="age">
</div>
</div>
<hr class="mb-4">
<button class="btn btn-primary btn-lg btn-block" type="submit" value="Submit">Добавить студента</button>
</div>
</div>
</form><?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<dependencies>
...
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
</dependencies>
...
</project>public class Student {
// Имя должно быть длиной от 2 до 50 символов
@Size(min = 2, max= 50, message = "First name should be from 2 to 50 characters")
private String firstName;
// Фамилия должна быть длиной от 2 до 50 символов
@Size(min = 2, max= 50, message = "Last name should be from 2 to 50 characters")
private String lastName;
// Возраст должен быть целым числом от 13 до 65
@Range(min = 13, max = 65, message = "Student age should be from 13 to 65 years")
private int age;
// Для валидации электронной почты используем регулярное выражение
@Pattern(regexp = "^[\\\\w!#$%&’*+/=?`{|}~^-]+(?:\\\\.[\\\\w!#$%&’*+/=?`{|}~^-]+)*@(?:[a-zA-Z0-9-]+\\\\.)+[a-zA-Z]{2,6}$",
message = "Invalid email format")
private String email;
...
} @GetMapping("/")
public String addStudent(Model model) {
model.addAttribute("student", new Student());
return "index";
}
@PostMapping("/")
public String processAddStudentForm(@Valid Student student, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
System.out.println("Validation has been failed!");
return "index";
}
System.out.println(student);
list.add(student);
return "redirect:/";
}<div class="col-md-6 mb-3">
<label for="lastName">Фамилия</label>
<input th:field="*{lastName}" type="text" class="form-control" id="lastName">
<small class="text-danger" th:if="${#fields.hasErrors('lastName')}" th:errors="*{lastName}"/>
</div><!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<title>Добавление студента</title>
</head>
<body class="bg-light">
<div class="container">
<div class="py-5 text-center">
<h2>Добавление студента</h2>
<p class="lead">Заполните поля и нажмите кнопку 'Добавить студента'</p>
</div>
<form enctype="multipart/form-data" action="#" th:action="@{/}" th:object="${student}" method="post">
<div class="row">
<div class="col-md-12">
<h4 class="mb-3">Поля для заполнения</h4>
<div class="row">
<div class="col-md-6 mb-3">
<label for="lastName">Фамилия</label>
<input th:field="*{lastName}" type="text" class="form-control" id="lastName">
<small class="text-danger" th:if="${#fields.hasErrors('lastName')}" th:errors="*{lastName}"/>
</div>
<div class="col-md-6 mb-3">
<label for="firstName">Имя</label>
<input th:field="*{firstName}" type="text" class="form-control" id="firstName">
<small class="text-danger" th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}"/>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="email">Электронная почта</label>
<input th:field="*{email}" type="text" class="form-control" id="email">
<small class="text-danger" th:if="${#fields.hasErrors('email')}" th:errors="*{email}"/>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="age">Возраст</label>
<input th:value="${student.age > 0} ? ${student.age} : ''" th:field="*{age}" type="number" class="form-control" id="age">
<small class="text-danger" th:if="${#fields.hasErrors('age')}" th:errors="*{age}"/>
</div>
</div>
<hr class="mb-4">
<button class="btn btn-primary btn-lg btn-block" type="submit" value="Submit">Добавить студента</button>
</div>
</div>
</form>
</div>
</div>
</div>
<br/><br/><br/>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
</body>
</html>public class Student {
// Имя должно быть длиной от 2 до 50 символов
@Size(min = 2, max= 50, message = "First name should be from 2 to 50 characters")
private String firstName;
// Фамилия должна быть длиной от 2 до 50 символов
@Size(min = 2, max= 50, message = "Last name should be from 2 to 50 characters")
private String lastName;
// Возраст должен быть целым числом от 13 до 65
@Range(min = 13, max = 65, message = "Student age should be from 13 to 65 years")
private int age;
// Для валидации электронной почты используем регулярное выражение
@Pattern(regexp = "^[a-zA-Z0-9_!#$%&’*+/=?`{|}~^.-]+@[a-zA-Z0-9.-]+$",
message = "Invalid email format")
private String email;
public Student(String firstName, String lastName, int age, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.email = email;
}
public Student() {
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}@Controller
public class StudentController {
private List<Student> list = new ArrayList<>();
@GetMapping("/")
public String addStudent(Model model) {
model.addAttribute("student", new Student());
return "index";
}
@PostMapping("/")
public String processAddStudentForm(@Valid Student student, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "index";
}
System.out.println(student);
list.add(student);
return "redirect:/";
}
}<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<title>Добавление студента</title>
</head>
<body class="bg-light">
<div class="container">
<div class="py-5 text-center">
<h2>Добавление студента</h2>
<p class="lead">Заполните поля и нажмите кнопку 'Добавить студента'</p>
</div>
<form enctype="multipart/form-data" action="#" th:action="@{/}" th:object="${student}" method="post">
<div class="row">
<div class="col-md-12">
<h4 class="mb-3">Поля для заполнения</h4>
<div class="row">
<div class="col-md-6 mb-3">
<label for="lastName">Фамилия</label>
<input th:field="*{lastName}" type="text" class="form-control" id="lastName">
<small class="text-danger" th:if="${#fields.hasErrors('lastName')}" th:errors="*{lastName}"/>
</div>
<div class="col-md-6 mb-3">
<label for="firstName">Имя</label>
<input th:field="*{firstName}" type="text" class="form-control" id="firstName">
<small class="text-danger" th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}"/>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="email">Электронная почта</label>
<input th:field="*{email}" type="text" class="form-control" id="email">
<small class="text-danger" th:if="${#fields.hasErrors('email')}" th:errors="*{email}"/>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="age">Возраст</label>
<input th:value="${student.age > 0} ? ${student.age} : ''" th:field="*{age}" type="number" class="form-control" id="age">
<small class="text-danger" th:if="${#fields.hasErrors('age')}" th:errors="*{age}"/>
</div>
</div>
<div class="form-group">
<label for="file">Choose file:</label>
<input type="file" name="file" class="form-control-file" id="file">
</div>
<hr class="mb-4">
<button class="btn btn-primary btn-lg btn-block" type="submit" value="Submit">Добавить студента</button>
</div>
</div>
</form>
</div>
</div>
</div>
<br/><br/><br/>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
</body>
</html>@Controller
public class StudentController {
private List<Student> list = new ArrayList<>();
@GetMapping("/")
public String addStudent(Model model) {
model.addAttribute("student", new Student());
return "index";
}
@PostMapping("/")
public String processAddStudentForm(@Valid Student student, @RequestParam("file") MultipartFile file, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "index";
}
System.out.println(student);
list.add(student);
// normalize the file path
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
// save the file on the local file system
try {
Path path = Paths.get("c:\\temp\\" + fileName);
Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
e.printStackTrace();
}
return "redirect:/";
}
}spring.servlet.multipart.max-file-size=128KB
spring.servlet.multipart.max-request-size=128KB
spring.servlet.multipart.enabled=true <dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>public interface Sender {
void sendMessage(String message, String target);
}public class TwitterSender implements Sender {
public void sendMessage(String message, String target) {
System.out.println("Tweet: " + message + " is sending to " + target);
}
}public class User {
private Sender sender;
public User(Sender sender) {
this.sender = sender;
}
public void setSender(Sender sender) {
this.sender = sender;
}
public void send(String message, String target) throws NullPointerException {
if (sender != null) {
sender.sendMessage(message, target);
} else {
throw new NullPointerException("Sender object is null");
}
}
}<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>@Configuration
public class AppConfig {...}@Configuration
public class AppConfig {
@Bean
public TwitterSender twitterSender() {
return new TwitterSender();
}
}@Configuration
public class AppConfig {
@Bean
public User user() {
return new User(twitterSender());
}
@Bean
public TwitterSender twitterSender() {
return new TwitterSender();
}
}public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(AppConfig.class);
User user = context.getBean(User.class);
user.send("Hello!", "Nick");
}
}июл 01, 2018 2:37:09 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4534b60d: startup date [Sun Jul 01 14:37:09 EEST 2018]; root of context hierarchy
Tweet: Hello! is sending to Nick@Component
public class TwitterSender implements Sender {...}
@Component
public class User {...}@Component
public class User {
private Sender sender;
@Autowired
public void setSender(Sender sender) {
this.sender = sender;
}
}@Configuration
@ComponentScan("app")
public class AppConfig {}июл 01, 2018 4:13:21 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2d8e6db6: startup date [Sun Jul 01 16:13:21 EEST 2018]; root of context hierarchy
Tweet: Hello! is sending to Nick@Component
public class EmailSender implements Sender {
public void sendMessage(String message, String target) {
System.out.println("Email: " + message + " to: " + target);
}
} at app.Main.main(Main.java:28)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'app.model.Sender' available: expected single matching bean but found 2: emailSender,twitterSendersender.type = emailpublic class Main {
public static final Properties config = new Properties();
static {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
try (InputStream resourceStream = loader.getResourceAsStream("app.properties")) {
config.load(resourceStream);
} catch (IOException e) {
e.printStackTrace();
}
}
}public class TwitterSenderCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return Main.config.getProperty("sender.type").matches("twitter");
}
}
public class EmailSenderCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return Main.config.getProperty("sender.type").matches("email");
}
}@Component
@Conditional(value = TwitterSenderCondition.class)
public class TwitterSender implements Sender {...}
@Component
@Conditional(value = EmailSenderCondition.class)
public class EmailSender implements Sender {...}июл 01, 2018 4:57:53 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2d8e6db6: startup date [Sun Jul 01 16:57:53 EEST 2018]; root of context hierarchy
Email: Hello! to: Nickиюл 01, 2018 4:58:56 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2d8e6db6: startup date [Sun Jul 01 16:58:56 EEST 2018]; root of context hierarchy
Tweet: Hello! is sending to Nickspring:
jpa:
database: POSTGRESQL
show-sql: true
hibernate:
ddl-auto: create-drop
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
datasource:
platform: postgres
url: jdbc:postgresql://ec2-176-34-183-20.eu-west-1.compute.amazonaws.com:5432/d60ukqmkatvcpg
username: xvlmxbawwxafdu
password: a1439fbcffbfdd6ad208df91670a37c73d8ed12d18cd6de91c1485c5841774b9
driverClassName: org.postgresql.DriverMicrosoft Windows [Version 10.0.18362.476]
(c) Корпорация Майкрософт (Microsoft Corporation), 2019. Все права защищены.
C:\Users\nickg>git config --global user.name "Mykola Hodovychenko"
C:\Users\nickg>git config --global user.email hodovychenko@opu.ua
C:\Users\nickg>git config --list
http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
http.sslbackend=openssl
diff.astextplain.textconv=astextplain
core.autocrlf=true
core.fscache=true
core.symlinks=false
core.editor="C:\\Program Files\\Notepad++\\notepad++.exe" -multiInst -notabbar -nosession -noPlugin
credential.helper=manager
user.name=Mykola Hodovychenko
user.email=hodovychenko@opu.ua
gui.recentrepo=E:/spring/testproject3
C:\Users\nickg>C:\Users\nickg>heroku login
heroku: Press any key to open up the browser to login or q to exit:
Opening browser to https://cli-auth.heroku.com/auth/browser/630e1a02-f90e-4217-8170-cd71d7fc700e
Logging in... done
Logged in as hodovychenko@opu.uaC:\Users\nickg>cd d:\springdemo\ejo
d:\springdemo\ejo>git init
Initialized empty Git repository in d:/springdemo/ejo/.git/d:\springdemo\ejo>heroku git:remote -a opnu-ej
set git remote heroku to https://git.heroku.com/opnu-ej.gitd:\springdemo\ejo>git add .
warning: LF will be replaced by CRLF in .gitignore.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in .mvn/wrapper/MavenWrapperDownloader.java.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in .mvn/wrapper/maven-wrapper.properties.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in mvnw.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in mvnw.cmd.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in pom.xml.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in src/main/java/com/example/ejo/EjoApplication.java.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in src/test/java/com/example/ejo/EjoApplicationTests.java.
The file will have its original line endings in your working directory
d:\springdemo\ejo>git commit -am "initial commit"
[master (root-commit) 162bc53] initial commit
16 files changed, 886 insertions(+)
create mode 100644 .gitignore
create mode 100644 .mvn/wrapper/MavenWrapperDownloader.java
create mode 100644 .mvn/wrapper/maven-wrapper.jar
create mode 100644 .mvn/wrapper/maven-wrapper.properties
create mode 100644 mvnw
create mode 100644 mvnw.cmd
create mode 100644 pom.xml
create mode 100644 src/main/java/com/example/ejo/Controller.java
create mode 100644 src/main/java/com/example/ejo/EjoApplication.java
create mode 100644 src/main/java/com/example/ejo/Group.java
create mode 100644 src/main/java/com/example/ejo/GroupRepository.java
create mode 100644 src/main/java/com/example/ejo/Service.java
create mode 100644 src/main/java/com/example/ejo/Student.java
create mode 100644 src/main/java/com/example/ejo/StudentRepository.java
create mode 100644 src/main/resources/application.yml
create mode 100644 src/test/java/com/example/ejo/EjoApplicationTests.javad:\springdemo\ejo>git push heroku master
Enumerating objects: 32, done.
Counting objects: 100% (32/32), done.
Delta compression using up to 6 threads
Compressing objects: 100% (23/23), done.
Writing objects: 100% (32/32), 54.39 KiB | 9.06 MiB/s, done.
Total 32 (delta 1), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Java app detected
remote: -----> Installing JDK 1.8... done
remote: -----> Executing: ./mvnw -DskipTests clean dependency:list install
remote: [INFO] Scanning for projects...
...
remote: [INFO] Replacing main artifact with repackaged archive
remote: [INFO]
remote: [INFO] --- maven-install-plugin:2.5.2:install (default-install) @ ejo ---
remote: [INFO] Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/shared/maven-shared-utils/0.4/maven-shared-utils-0.4.pom
remote: [INFO] Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/shared/maven-shared-utils/0.4/maven-shared-utils-0.4.pom (4.0 kB at 450 kB/s)
remote: [INFO] Downloading from central: https://repo.maven.apache.org/maven2/classworlds/classworlds/1.1-alpha-2/classworlds-1.1-alpha-2.jar
remote: [INFO] Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/shared/maven-shared-utils/0.4/maven-shared-utils-0.4.jar
remote: [INFO] Downloaded from central: https://repo.maven.apache.org/maven2/classworlds/classworlds/1.1-alpha-2/classworlds-1.1-alpha-2.jar (38 kB at 1.1 MB/s)
remote: [INFO] Downloading from central: https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-utils/3.0.15/plexus-utils-3.0.15.jar
remote: [INFO] Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/shared/maven-shared-utils/0.4/maven-shared-utils-0.4.jar (155 kB at 2.0 MB/s)
remote: [INFO] Downloaded from central: https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-utils/3.0.15/plexus-utils-3.0.15.jar (239 kB at 3.0 MB/s)
remote: [INFO] Installing /tmp/build_bee447e74484e663663b1d166f8e9456/target/ejo-0.0.1-SNAPSHOT.jar to /app/tmp/cache/.m2/repository/com/example/ejo/0.0.1-SNAPSHOT/ejo-0.0.1-SNAPSHOT.jar
remote: [INFO] Installing /tmp/build_bee447e74484e663663b1d166f8e9456/pom.xml to /app/tmp/cache/.m2/repository/com/example/ejo/0.0.1-SNAPSHOT/ejo-0.0.1-SNAPSHOT.pom
remote: [INFO] ------------------------------------------------------------------------
remote: [INFO] BUILD SUCCESS
remote: [INFO] ------------------------------------------------------------------------
remote: [INFO] Total time: 20.474 s
remote: [INFO] Finished at: 2019-11-26T21:46:52Z
remote: [INFO] ------------------------------------------------------------------------
remote: -----> Discovering process types
remote: Procfile declares types -> (none)
remote: Default types for buildpack -> web
remote:
remote: -----> Compressing...
remote: Done: 84.1M
remote: -----> Launching...
remote: Released v5
remote: https://opnu-ej.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/opnu-ej.git
* [new branch] master -> master
d:\springdemo\ejo><dependencies>
...
<!-- jpa, crud repository -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- PostgreSQL -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
</dependencies>spring:
jpa:
database: POSTGRESQL
show-sql: true
hibernate:
ddl-auto: create-drop
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
datasource:
platform: postgres
url: jdbc:postgresql://localhost:5432/ejournal
username: ejournal_user
password: 123456
driverClassName: org.postgresql.Driver@Entity
@Table(name = "students")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
private int age;
}<dependencies>
...
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>@Entity
@Table(name = "students")
@Data
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
private int age;
}@org.springframework.stereotype.Service
public class Service {
public void addStudent(Student student, int id) {
// Добавление нового студента
}
public List<Student> getAllStudents() {
// Получение списка студентов
}
}@RestController
public class Controller {
@Autowired
private Service service;
@PostMapping("/student")
public void addStudent(@RequestBody Student student) {
service.addStudent(student);
}
@GetMapping("/student")
public List<Student> getAllStudents() {
return service.getAllStudents();
}
}@Entity
@Table(name = "groups")
@Data
public class Group {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
@OneToMany(mappedBy = "group")
private List<Student> studentList;
}public interface StudentRepository extends JpaRepository<Student, Integer> {
}@org.springframework.stereotype.Service
public class Service {
@Autowired
private StudentRepository studentRepo;
public void addStudent(Student student) {
studentRepo.save(student);
}
public List<Student> getAllStudents() {
return studentRepo.findAll();
}
}@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String firstname;
private String lastname;
private int age;
@ManyToOne (fetch = FetchType.LAZY,optional = false)
@JoinColumn(name = "group_id",nullable = false)
@JsonIgnore
private Group group;
}@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "groups")
public class Group {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
@OneToMany(mappedBy = "group", cascade = CascadeType.ALL)
private List<Student> students;
public void addStudent(Student student) {
students.add(student);
}
}@RestController
public class Controller {
@Autowired
private Service service;
@PostMapping("/student/{group_id}")
public void addStudent(@RequestBody Student student, @PathVariable(name = "group_id") int group_id) {
service.addStudent(student, group_id);
}
@GetMapping("/student")
public List<Student> getAllStudents() {
return service.getAllStudents();
}
@PostMapping("/group")
public void addGroup(@RequestBody Group group) {
service.addGroup(group);
}
@GetMapping("/group")
public List<Group> getAllGroups() {
return service.getAllGroups();
}
}public interface GroupRepository extends JpaRepository<Group, Integer> {}@org.springframework.stereotype.Service
public class Service {
@Autowired
private StudentRepository studentRepo;
@Autowired
private GroupRepository groupRepo;
public void addStudent(Student student, int id) {
Group g = groupRepo.getOne(id);
student.setGroup(g);
studentRepo.save(student);
}
public List<Student> getAllStudents() {
return studentRepo.findAll();
}
public void addGroup(Group group) {
groupRepo.saveAndFlush(group);
}
public List<Group> getAllGroups() {
return groupRepo.findAll();
}
}<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
...
</dependencies><dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>@Service
public class JwiUtil {
private String PRIVATE_KEY = "670d4918c206e1bfec75bcaf637dc5b8";
private String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return createToken(claims, userDetails.getUsername());
}
private String createToken(Map<String, Object> claims, String subject) {
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 8))
.signWith(SignatureAlgorithm.HS512, PRIVATE_KEY).compact();
}
}@Service
public class JwiUtil {
private String PRIVATE_KEY = "670d4918c206e1bfec75bcaf637dc5b8";
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return createToken(claims, userDetails.getUsername());
}
private String createToken(Map<String, Object> claims, String subject) {
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 8))
.signWith(SignatureAlgorithm.HS512, PRIVATE_KEY).compact();
}
public boolean validateToken(String token, UserDetails userDetails) {
final String username = extractUsername(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
private boolean isTokenExpired(String token) {
return extractExpiration(token).before(new Date());
}
private String extractUsername(String token) {
return extractClaim(token, Claims::getSubject);
}
private Date extractExpiration(String token) {
return extractClaim(token, Claims::getExpiration);
}
private <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}
private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(PRIVATE_KEY).parseClaimsJws(token).getBody();
}
}@Data
public class AuthRequest {
private String username;
private String password;
}@Data
public class AuthResponse {
private final String jwt;
}


















spring:
security:
user:
name: nick
password: 1234@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
}@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
}
}@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("foo")
.password("bar")
.roles("USER");
}
}@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("foo")
.password("bar")
.roles("USER")
.and()
.withUser("nick")
.roles("MODERATOR");
}
}@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("foo")
.password("$2y$12$kElDOfhm4WgdsDc4UQjgtuz0VEi5MOqVVhXaMoD1F2lhLivokhCqe")
.roles("USER")
.and()
.withUser("nick")
.roles("MODERATOR");
}
@Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("foo")
.password("{bcrypt}$2y$12$.JzV1A3qlof1.NzZpGaTYO1b26JGHevg0900QvwrSOdU3U9.g4hta")
.roles("USER");
}
// @Bean
// public PasswordEncoder getPasswordEncoder() {
// return new BCryptPasswordEncoder();
// }
}@Controller
public class IndexController {
@GetMapping("/")
public String index() {
return "index";
}
@GetMapping("/user/index")
public String user_index() {
return "/user/index";
}
@GetMapping("/admin/index")
public String admin_index() {
return "/admin/index";
}
}@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("foo")
.password("$2y$12$kElDOfhm4WgdsDc4UQjgtuz0VEi5MOqVVhXaMoD1F2lhLivokhCqe")
.roles("USER")
.and()
.withUser("admin")
.password("$2y$12$DQlTV6V1wMKEoCIW5lo1huAn2/bRk4hULDmRS5Jw6YW7HayHV4K66")
.roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "static/css", "static/js").permitAll()
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.antMatchers("/admin/**").hasRole("ADMIN")
.and().formLogin();
}
@Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}@Service
public class MyUserDetailsService implements UserDetailsService {
@Autowired
UserRepository repository;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
return new MyUserDetails(s);
}
}public class MyUserDetails implements UserDetails {
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
}
private String userName;
public MyUserDetails(String userName) {
this.userName = userName;
}
public MyUserDetails() {
}
@Override
public String getPassword() {
return "$2y$12$8fKhxW71f4DzkzXYCh592.I.cd1uKkMrNwrHAApR1x5KHJ3qy1IjS";
}
@Override
public String getUsername() {
return userName;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- PostgreSQL -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency> jpa:
database: POSTGRESQL
show-sql: true
hibernate:
ddl-auto: create-drop
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
datasource:
platform: postgres
url: jdbc:postgresql://localhost:5432/ejournal
username: ejournal_user
password: 123456
driverClassName: org.postgresql.Driver@Entity
@Table(name = "profile")
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "user_name")
private String userName;
private String password;
private boolean active;
private String roles;
}@Service
public class MyUserDetailsService implements UserDetailsService {
@Autowired
UserRepository repository;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
Optional<User> user = repository.findByUserName(s);
user.orElseThrow(() -> new UsernameNotFoundException("User not found: " + s));
return user.map(MyUserDetails::new).get();
}
}public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findByUserName(String userName);
}public class MyUserDetails implements UserDetails {
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorityList;
}
private String userName;
private String password;
private boolean active;
private List<GrantedAuthority> authorityList;
public MyUserDetails(User userName) {
this.userName = userName.getUserName();
this.password = userName.getPassword();
this.active = userName.isActive();
this.authorityList = Arrays.stream(userName.getRoles().split(",")).map(SimpleGrantedAuthority::new).collect(Collectors.toList());
}
public MyUserDetails() {
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return userName;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return active;
}
}@org.springframework.web.bind.annotation.RestController
public class RestController {
@Autowired
private AuthenticationManager authManager;
@Autowired
private JwtUtil jwiUtil;
@Autowired
MyUserDetailsService userDetailsService;
@PostMapping(value = "/auth")
public ResponseEntity<?> createAuthToken(@RequestBody AuthRequest request) throws BadCredentialsException {
try {
authManager.authenticate(
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
);
} catch (BadCredentialsException ex) {
ex.printStackTrace();
}
final UserDetails userDetails = userDetailsService.loadUserByUsername(request.getUsername());
final String jwt = jwiUtil.generateToken(userDetails);
return ResponseEntity.ok(new AuthResponse(jwt));
}
}@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
MyUserDetailsService userDetailsService;
@Autowired
JwtRequestFilter filter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
// Авторизация
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/", "static/css", "static/js").permitAll()
.antMatchers("/auth").permitAll()
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.antMatchers("/admin/**").hasRole("ADMIN")
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}@GetMapping(value = "/helloworld")
public String helloWorldRequest(Principal principal) {
final UserDetails userDetails = userDetailsService.loadUserByUsername(principal.getName());
return "<h1>Hello " + userDetails.getAuthorities().toString() + " </h1>";
}@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/", "static/css", "static/js").permitAll()
.antMatchers("/auth").permitAll()
.antMatchers("/helloworld").authenticated()
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.antMatchers("/admin/**").hasRole("ADMIN")
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private JwtUtil jwtUtil;
@Autowired
MyUserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
final String authHeader = httpServletRequest.getHeader("Authorization");
String jwt = null;
String username = null;
if (authHeader != null && authHeader.startsWith("Bearer ")) {
jwt = authHeader.substring(7);
username = jwtUtil.extractUsername(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtUtil.validateToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(token);
}
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// Авторизация
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/", "static/css", "static/js").permitAll()
.antMatchers("/auth").permitAll()
.antMatchers("/helloworld","/me").authenticated()
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.antMatchers("/admin/**").hasRole("ADMIN")
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
}
}
























