рд╣рдо рд╡реЗрдм рдлреНрд░реЗрдорд╡рд░реНрдХ, рдмрд╛рд╣рд░реА рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдФрд░ рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕рд░реНрд╡рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛ рдПрдХ рдЫреЛрдЯрд╛ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓рд┐рдЦреЗрдВрдЧреЗред
рдЗрд╕ рд▓реЗрдЦ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдПрдХ рд╡реЗрдм рд╕реЗрд╡рд╛ рдХреЗ рд╣реБрдб рдХреЗ рддрд╣рдд рдЬреЛ рдХреБрдЫ рднреА рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдЙрд╕рдХреЗ рд╕рд╛рдорд╛рдиреНрдп рд╕рд╛рд░ рдХреЛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдЬрд╛рд╡рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рджрд┐рдЦрд╛рдирд╛ рд╣реИред рддреЛ рдЪрд▓рд┐рдП рдЪрд▓рддреЗ рд╣реИрдВред рд╣рдореЗрдВ рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ, рд╕рд╛рде рд╣реА рдПрдХ рд╕рд░реНрд╡рд▓реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕рд▓рд┐рдП, рдЗрд╕ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдорд╛рд╡реЗрди рджреНрд╡рд╛рд░рд╛ рдЗрдХрдЯреНрдард╛ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рдмрд┐рдирд╛ред
рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЗ рдПрдбреНрд░реЗрд╕ рдмрд╛рд░ рдореЗрдВ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдЖрдИрдкреА-рдПрдбреНрд░реЗрд╕ (рдпрд╛ рдПрдХ рдЖрдИрдкреА рдПрдбреНрд░реЗрд╕ рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ) рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ? рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкреЛрд░реНрдЯ рдкрд░, рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╣реЛрд╕реНрдЯ рдХреЗ ServerSocket рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдиреБрд░реЛрдз рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рд╣рдо рдЕрдкрдиреА рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ рдкрд░ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдПрдХ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдореБрдХреНрдд рдмрдВрджрд░рдЧрд╛рд╣ рдкрд░ рд╕реЙрдХреЗрдЯ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП 9001)ред
public class HttpRequestSocket { private static volatile Socket socket; private HttpRequestSocket() { } public static Socket getInstance() throws IOException { if (socket == null) { synchronized (HttpRequestSocket.class) { if (socket == null) { socket = new ServerSocket(9001).accept(); } } } return socket; } }
рдпрд╣ рдордд рднреВрд▓реЛ рдХрд┐ рдмрдВрджрд░рдЧрд╛рд╣ рдкрд░ рд╢реНрд░реЛрддрд╛, рдПрдХ рд╡рд╕реНрддреБ рдХреЗ рд░реВрдк рдореЗрдВ, рдПрдХ рд╣реА рдкреНрд░рддрд┐ рдореЗрдВ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд╡рд╛рдВрдЫрдиреАрдп рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╕рд┐рдВрдЧрд▓рдЯрди (рдЬрд░реВрд░реА рдирд╣реАрдВ рдХрд┐ рдбрдмрд▓-рдЪреЗрдХ рд╣реЛ, рд▓реЗрдХрд┐рди рдРрд╕рд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ)ред
рдкреЛрд░реНрдЯ 9001 рдкрд░ рд╣рдорд╛рд░реЗ рд╣реЛрд╕реНрдЯ-рдП (рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ) рдкрд░, рдПрдХ рд╢реНрд░реЛрддрд╛ рд╣реИ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдмрд╛рдЗрдЯреНрд╕ рдХреА рдПрдХ рдзрд╛рд░рд╛ рдХреЗ рд░реВрдк рдореЗрдВ рджрд░реНрдЬ рдХрд░рддрд╛ рд╣реИред
рдпрджрд┐ рдЖрдк DataInputStream рдореЗрдВ рд╕реЙрдХреЗрдЯ рд╕реЗ рдмрд╛рдЗрдЯ [] рдШрдЯрд╛рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рдорд┐рд▓рддрд╛ рд╣реИ:
GET /index HTTP/1.1 Host: localhost:9001 Connection: keep-alive Cache-Control: no-cache Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36 Postman-Token: 838f4680-a363-731d-aa74-10ee46b9a87a Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7
рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рд╣реЗрдбрд░ рдХреЗ рд╕рд╛рде рдорд╛рдирдХ Http рдЕрдиреБрд░реЛрдзред
рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП, рд╣рдо рдбрд┐рдлрд╝реЙрд▓реНрдЯ рддрд░реАрдХреЛрдВ рд╕реЗ рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рдЙрдкрдпреЛрдЧ-рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛рддреЗ рд╣реИрдВ, рдореЗрд░реА рд░рд╛рдп рдореЗрдВ рдпрд╣ рдЗрд╕ рддрд░рд╣ рдХреЗ рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдлреА рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ (рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрджрд┐ рдпрд╣ рдЕрднреА рднреА рд╕реНрдкреНрд░рд┐рдВрдЧ рд╣реИ, рддреЛ рд╣рдо рдХрдХреНрд╖рд╛ рдореЗрдВ рдирд┐рд░реНрднрд░рддрд╛ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХрдо рдХрд░ рджреЗрддреЗ рд╣реИрдВ)ред
public interface InputStringUtil { default String parseRequestMapping(final String inputData) { return inputData.split((" "))[1]; } default RequestType parseRequestType(final String source) { return valueOf(source.split(("/"))[0].trim()); } default Map<String, String> parseRequestParameter(final String source) { if (parseRequestType(source) == GET) { return parseGetRequestParameter(source); } else { return parsePostRequestParameter(source); } } @SuppressWarnings("unused") class ParameterParser { static Map<String, String> parseGetRequestParameter(final String source) { final Map<String, String> parameterMap = new HashMap<>(); if(source.contains("?")){ final String parameterBlock = source.substring(source.indexOf("?") + 1, source.indexOf("HTTP")).trim(); for (final String s : parameterBlock.split(Pattern.quote("&"))) { parameterMap.put(s.split(Pattern.quote("="))[0], s.split(Pattern.quote("="))[1]); } } return parameterMap; } static Map<String, String> parsePostRequestParameter(final String source) {
рдпрд╣ рдЙрдкрдпреЛрдЧ GET рдФрд░ POST рджреЛрдиреЛрдВ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдкреНрд░рдХрд╛рд░, url рдФрд░ рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рд╕реВрдЪреА рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░ рд╕рдХрддрд╛ рд╣реИред
рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ, рд╣рдо рдЕрдиреБрд░реЛрдз рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд╕рд╛рде рд▓рдХреНрд╖реНрдп рдпреВрдЖрд░рдПрд▓ рдФрд░ рдорд╛рдирдЪрд┐рддреНрд░ рдХреЗ рд╕рд╛рде рдЕрдиреБрд░реЛрдз рдореЙрдбрд▓ рдмрдирд╛рддреЗ рд╣реИрдВред
рд╣рдорд╛рд░реА рд╕реЗрд╡рд╛ рдХрд╛ рдирд┐рдпрдВрддреНрд░рдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд▓рд┐рдП рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рдЕрдореВрд░реНрдд рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдХрд┐рддрд╛рдмреЗрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ (рдЗрд╕ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ, рдмрд╕ рд╕реВрдЪреА рдореЗрдВ), рдкреБрд╕реНрддрдХреЛрдВ рдХреЛ рд╣рдЯрд╛ рджреЗрдВ рдФрд░ рд╕рднреА рдкреБрд╕реНрддрдХреЛрдВ рдХреА рд╕реВрдЪреА рд╡рд╛рдкрд╕ рдХрд░ рджреЗрдВред
1. рдирд┐рдпрдВрддреНрд░рдХ
public class BookController { private static volatile BookController bookController; private BookController() { } public static BookController getInstance() { if (bookController == null) { synchronized (BookController.class) { if (bookController == null) { bookController = new BookController(); } } } return bookController; } @RequestMapping(path = "/index") @SuppressWarnings("unused") public void index(final Map<String, String> paramMap) { final Map<String, List<DomainBook>> map = new HashMap<>(); map.put("book", DefaultBookService.getInstance().getCollection()); HtmlMarker.getInstance().makeTemplate("index", map); } @RequestMapping(path = "/add") @SuppressWarnings("unused") public void addBook(final Map<String, String> paramMap) { DefaultBookService.getInstance().addBook(paramMap); final Map<String, List<DomainBook>> map = new HashMap<>(); map.put("book", DefaultBookService.getInstance().getCollection()); HtmlMarker.getInstance().makeTemplate("index", map); } }
рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╕рд┐рдВрдЧрд▓рдЯрди рдХрдВрдЯреНрд░реЛрд▓рд░ рднреА рд╣реИред
рд╣рдо RequestMapping рд░рдЬрд┐рд╕реНрдЯрд░ рдХрд░рддреЗ рд╣реИрдВред рдмрдВрдж рдХрд░реЛ, рд╣рдо рдЗрд╕реЗ рдПрдХ рдврд╛рдВрдЪреЗ рдХреЗ рдмрд┐рдирд╛ рдХрд░рддреЗ рд╣реИрдВ, рдХреНрдпрд╛ RequestMapping? рдпрд╣ рдПрдиреЛрдЯреЗрд╢рди рд╣рдореЗрдВ рдЦреБрдж рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ред
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface RequestMapping { String path() default "/"; }
рдпрд╣ рднреА рд╕рдВрднрд╡ рдерд╛ рдХрд┐
рдХрдВрдЯреНрд░реЛрд▓рд░ рдПрдиреЛрдЯреЗрд╢рди рдХреЛ рдХреНрд▓рд╛рд╕ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдП рдФрд░, рдПрдкреНрд▓реАрдХреЗрд╢рди рд╕реНрдЯрд╛рд░реНрдЯрдЕрдк рдкрд░, рдЗрд╕ рдПрдиреЛрдЯреЗрд╢рди рдФрд░ рдЙрдирдХреЗ рддрд░реАрдХреЛрдВ рд╕реЗ рдЪрд┐рд╣реНрдирд┐рдд рд╕рднреА рдХреНрд▓рд╛рд╕реЗрд╕ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░реЗрдВ, рдФрд░ рдЙрдиреНрд╣реЗрдВ рдпреВрдЖрд░рдПрд▓ рдореИрдкрд┐рдВрдЧ рд╕реЗ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдореИрдк рдореЗрдВ рдЬреЛрдбрд╝реЗрдВред рд▓реЗрдХрд┐рди рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рд╣рдо рдЦреБрдж рдХреЛ рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ рддрдХ рд╕реАрдорд┐рдд рдХрд░ рд▓реЗрдВрдЧреЗред
рдирд┐рдпрдВрддреНрд░рдХ рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд░ рд╣реЛрдЧрд╛, рдЬреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЗ рдореЙрдбрд▓ рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдореЙрдбрд▓ рдХреЛ рдмрдирд╛рдПрдЧрд╛ рдФрд░ рдирд┐рдпрдВрддреНрд░рдХ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдореИрдк рдХрд░реЗрдЧрд╛ред
public class HttpRequestPreProcessor implements InputStringUtil { private final byte[] BYTE_BUFFER = new byte[1024]; public void doRequest() { try { while (true) { System.out.println("Socket open"); final Socket socket = HttpRequestSocket.getInstance(); final DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); final String inputUrl = new String(BYTE_BUFFER, 0, in.read(BYTE_BUFFER)); processRequest(inputUrl); System.out.println("send request " + inputUrl); } } catch (final IOException e) { e.printStackTrace(); } } private void processRequest(final String inputData) { final String urlMapping = parseRequestMapping(inputData); final Map<String, String> paramMap = parseRequestParameter(inputData); final Method[] methods = BookController.getInstance().getClass().getMethods(); for (final Method method : methods) { if (method.isAnnotationPresent(RequestMapping.class) && urlMapping.contains(method.getAnnotation(RequestMapping.class).path())) { try { method.invoke(BookController.getInstance(), paramMap); return; } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } } HtmlMarker.getInstance().makeTemplate("error", emptyMap()); }
2. рдореЙрдбрд▓
рдПрдХ рдореЙрдбрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдХреНрд▓рд╛рд╕ рдмреБрдХ рд╣реЛрдЧреА
public class DomainBook { private String id; private String author; private String title; public DomainBook(String id, String author, String title) { this.id = id; this.author = author; this.title = title; } public String getId() { return id; } public String getAuthor() { return author; } public String getTitle() { return title; } @Override public String toString() { return "id=" + id + " author='" + author + '\'' + " title='" + title + '\''; } }
рдФрд░ рд╕реЗрд╡рд╛
public class DefaultBookService implements BookService { private static volatile BookService bookService; private List<DomainBook> bookList = new ArrayList<>(); private DefaultBookService() { } public static BookService getInstance() { if (bookService == null) { synchronized (DefaultBookService.class) { if (bookService == null) { bookService = new DefaultBookService(); } } } return bookService; } @Override public List<DomainBook> getCollection() { System.out.println("get collection " + bookList); return bookList; } @Override public void addBook(Map<String, String> paramMap) { final DomainBook domainBook = new DomainBook(paramMap.get("id"), paramMap.get("author"), paramMap.get("title")); bookList.add(domainBook); System.out.println("add book " + domainBook); } @Override public void deleteBookById(long id) {
рдЬреЛ рдкреБрд╕реНрддрдХреЛрдВ рдХрд╛ рдПрдХ рд╕рдВрдЧреНрд░рд╣ рдПрдХрддреНрд░ рдХрд░реЗрдЧрд╛, рдФрд░ рд╕реЗрд╡рд╛ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдореЙрдбрд▓ (рдХреБрдЫ рдорд╛рдирдЪрд┐рддреНрд░) рдбреЗрдЯрд╛ рдореЗрдВ рдбрд╛рд▓ рджреЗрдЧрд╛ред
3. рджреГрд╢реНрдп
рдПрдХ рджреГрд╢реНрдп рдХреЗ рд░реВрдк рдореЗрдВ, рд╣рдо рдПрдХ HTML рдЯреЗрдореНрдкрд▓реЗрдЯ рдмрдирд╛рдПрдВрдЧреЗ, рдФрд░ рдЗрд╕реЗ рдПрдХ рдЕрд▓рдЧ рд╕рдВрд╕рд╛рдзрдиреЛрдВ / рдкреГрд╖реНрдареЛрдВ рдХреА рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рд░рдЦреЗрдВрдЧреЗ, рдЬрд┐рд╕рд╕реЗ рдкреНрд░рд╕реНрддреБрддрд┐ рдХрд╛ рд╕реНрддрд░ рдЖрдЧреЗ рдмрдврд╝реЗрдЧрд╛ред
<html> <head> <title>Example</title> </head> <br> <table> <td>${book.id}</td><td>${book.author}</td><td>${book.title}</td> </table> </br> </br> </br> <form method="get" action="/add"> <p>Number<input type="text" name="id"></p> <p>Author<input type="text" name="author"></p> <p>Title<input type="text" name="title"></p> <p><input type="submit" value="Send"></p> </form> </body> </html>
рд╣рдо рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рдЯреЗрдореНрдкрд▓реЗрдЯ рдЗрдВрдЬрди рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рд╡рд░реНрдЧ рдХреЛ рд╕реЗрд╡рд╛ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдЖрд╡рд╢реНрдпрдХ http рд╣реИрдбрд░ рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП (рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, OK рдпрд╛ BAD REQUEST), HTML рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рдЪрд░ рдХреЛ рдореЙрдбрд▓ рд╕реЗ рдорд╛рдиреЛрдВ рдХреЗ рд╕рд╛рде рдмрджрд▓реЗрдВ, рдФрд░ рдЕрдВрдд рдореЗрдВ рдкреВрд░реНрдг рдПрдЪрдЯреАрдПрдордПрд▓ рдкреНрд░рд╕реНрддреБрдд рдХрд░реЗрдВ рдЬрд┐рд╕реЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕рдордЭ рд╕рдХрддреЗ рд╣реИрдВред
public class HtmlMarker { private static volatile HtmlMarker htmlMarker; private HtmlMarker() { } public static HtmlMarker getInstance() { if (htmlMarker == null) { synchronized (HtmlMarker.class) { if (htmlMarker == null) { htmlMarker = new HtmlMarker(); } } } return htmlMarker; } public void makeTemplate(final String fileName, Map<String, List<DomainBook>> param) { try { final BufferedWriter bufferedWriter = new BufferedWriter( new OutputStreamWriter( new BufferedOutputStream(HttpRequestSocket.getInstance().getOutputStream()), StandardCharsets.UTF_8)); if (fileName.equals("error")) { bufferedWriter.write(ERROR + ERROR_MESSAGE.length() + OUTPUT_END_OF_HEADERS + readFile(fileName, param)); bufferedWriter.flush(); } else { bufferedWriter.write(SUCCESS + readFile(fileName, param).length() + OUTPUT_END_OF_HEADERS + readFile(fileName, param)); bufferedWriter.flush(); } } catch (IOException e) { e.printStackTrace(); } } private String readFile(final String fileName, Map<String, List<DomainBook>> param) { final StringBuilder builder = new StringBuilder(); final String path = "src\\resources\\pages\\" + fileName + ".html"; try (BufferedReader br = Files.newBufferedReader(Paths.get(path))) { String line; while ((line = br.readLine()) != null) { if (line.contains("${")) { final String key = line.substring(line.indexOf("{") + 1, line.indexOf("}")); final String keyPrefix = key.split(Pattern.quote("."))[0]; for (final DomainBook domainBook : param.get(keyPrefix)) { builder.append("<tr>"); builder.append( line.replace("${book.id}", domainBook.getId()) .replace("${book.author}", domainBook.getAuthor()) .replace("${book.title}", domainBook.getTitle()) ).append("</tr>"); } if(param.get(keyPrefix).isEmpty()){ builder.append(line.replace("${book.id}</td><td>${book.author}</td><td>${book.title}", "<p>library is EMPTY</p>")); } continue; } builder.append(line).append("\n"); } return builder.toString(); } catch (IOException e) { e.printStackTrace(); } return ""; } }
рдкреНрд░рджрд░реНрд╢рди рдХреЗ рд▓рд┐рдП рдЖрд╡реЗрджрди рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд░реВрдк рдореЗрдВ, рд╣рдо рдЕрдкрдиреЗ рдЖрд╡реЗрджрди рдореЗрдВ рдХреБрдЫ рдкреБрд╕реНрддрдХреЛрдВ рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ:

рдЕрдВрдд рддрдХ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рд▓реЗрдЦ рдХреЗрд╡рд▓ рдорд╛рд░реНрдЧрджрд░реНрд╢рди рдХреЗ рд▓рд┐рдП рд╣реИ, рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рдереЛрдбрд╝рд╛ рджрд┐рд▓рдЪрд╕реНрдк рдФрд░ рдереЛрдбрд╝рд╛ рдЙрдкрдпреЛрдЧреА рдерд╛ред