Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ bin/

### Mac OS ###
.DS_Store\ntomcat.8080/

## tomcat
**/tomcat.8080
29 changes: 29 additions & 0 deletions src/main/java/com/diy/app/Lecture.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.diy.app;

import java.math.BigDecimal;

public class Lecture {

private Long id;
private String name;
private BigDecimal price;

public Lecture() {
}

public Long getId() {
return id;
}

public String getName() {
return name;
}

public BigDecimal getPrice() {
return price;
}

public void setId(Long id) {
this.id = id;
}
}
20 changes: 20 additions & 0 deletions src/main/java/com/diy/app/LectureApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.diy.app;

import com.diy.framework.web.mvc.Controller;
import com.diy.framework.web.server.TomcatWebServer;
import com.diy.framework.web.servlet.DispatcherServlet;

import java.util.HashMap;
import java.util.Map;

public class LectureApplication {
public static void main(String[] args) {
final Map<String, Controller> controllerMapping = new HashMap<>();
final LectureRepository lectureRepository = new LectureMapRepositoryImpl();
controllerMapping.put("/lectures", new LectureController(lectureRepository));

final DispatcherServlet servlet = new DispatcherServlet(controllerMapping);
final TomcatWebServer tomcatWebServer = new TomcatWebServer(servlet);
tomcatWebServer.start();
}
}
57 changes: 57 additions & 0 deletions src/main/java/com/diy/app/LectureController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.diy.app;

import com.diy.framework.web.mvc.Controller;
import com.diy.framework.web.mvc.view.ModelAndView;
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class LectureController implements Controller {

// private final Map<Long, Lecture> lectureRepository = new HashMap<>();
private final LectureRepository lectureRepository;

public LectureController(final LectureRepository lectureRepository) {
this.lectureRepository = lectureRepository;
}

@Override
public ModelAndView handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception {
if ("POST".equals(request.getMethod())) {
return doPost(request, response);
} else if ("GET".equals(request.getMethod())) {
return doGet(request, response);
}

throw new RuntimeException("404 Not Found");
}

private ModelAndView doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
final byte[] bodyBytes = req.getInputStream().readAllBytes();
final String body = new String(bodyBytes, StandardCharsets.UTF_8);

final Lecture lecture = new ObjectMapper().readValue(body, Lecture.class);

final long id = lectureRepository.size();
lectureRepository.put(id, lecture);
lecture.setId(id);

return new ModelAndView("redirect:/lectures");
}

private ModelAndView doGet(final HttpServletRequest req, final HttpServletResponse resp) throws Exception {
final Collection<Lecture> lectures = lectureRepository.values();
final Map<String, Object> model = new HashMap<>();
final Object lectureModels = lectures.stream().map(lecture -> Map.of("id", lecture.getId(), "name", lecture.getName(), "price", lecture.getPrice())).toList();
model.put("lectures", lectureModels);

return new ModelAndView("lecture-list", model);
}
}
52 changes: 52 additions & 0 deletions src/main/java/com/diy/app/LectureMapRepositoryImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.diy.app;

import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;

public class LectureMapRepositoryImpl implements LectureRepository{
ConcurrentHashMap<Long, Lecture> lectureMap = new ConcurrentHashMap<>();

@Override
public Lecture findById(Long id) {
return lectureMap.getOrDefault(id, null);
}

@Override
public void put(Long id, Lecture lecture) {
lectureMap.put(id, lecture);
}

@Override
public void remove(Long id) {
lectureMap.remove(id);
}

@Override
public void update(Lecture lecture) {
lectureMap.put(lecture.getId(), lecture);
}

@Override
public long size() {
return lectureMap.size();
}

@Override
public Collection<Lecture> values() {
return lectureMap.values();
}

@Override
public Collection<Lecture> values(int start, int end) {
if (start > end) {
throw new IllegalArgumentException("start must be less than end");
}

ArrayList<Lecture> lectures = new ArrayList<>(end - start + 1);
for (int i = 0; i < end - start + 1; i++) {
lectures.add(lectureMap.get(start + i));
}
return lectures;
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/diy/app/LectureRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.diy.app;

import java.util.Collection;

public interface LectureRepository {
public Lecture findById(Long id);
public void put(Long id, Lecture lecture);
public void remove(Long id);
public void update(Lecture lecture);
public long size();
public Collection<Lecture> values();
public Collection<Lecture> values(int start, int end);
}
6 changes: 0 additions & 6 deletions src/main/java/com/diy/app/Main.java

This file was deleted.

11 changes: 11 additions & 0 deletions src/main/java/com/diy/framework/web/mvc/Controller.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.diy.framework.web.mvc;

import com.diy.framework.web.mvc.view.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@FunctionalInterface
public interface Controller {
ModelAndView handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception;
}
79 changes: 79 additions & 0 deletions src/main/java/com/diy/framework/web/mvc/view/HtmlView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.diy.framework.web.mvc.view;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HtmlView implements View {

final Pattern pattern = Pattern.compile("<!--\\s*\"\\$\\{([^}]+)\\}\"\\s*-->");

private final String viewName;

public HtmlView(final String viewName) {
this.viewName = viewName;
}

@Override
public void render(final Map<String, ?> model, final HttpServletRequest req, final HttpServletResponse res) throws IOException {
final String viewFile = readViewFile(req, model);

res.setContentType("text/html;charset=utf-8");
final PrintWriter writer = res.getWriter();
writer.print(viewFile);
}

private String readViewFile(final HttpServletRequest req, final Map<String, ?> model) {
final StringBuilder content = new StringBuilder();

final String viewPath = getViewPath(req);
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(viewPath), StandardCharsets.UTF_8))) {
String line;


while ((line = reader.readLine()) != null) {
final Matcher matcher = pattern.matcher(line);

if (matcher.find()) {
final String modelKey = matcher.group(1);
final List<Map<String, ?>> lectures = (List<Map<String, ?>>) model.get(modelKey);

lectures.forEach(lecture -> {
lecture.forEach((key, value) ->
content.append("<li>")
.append(key)
.append(": ")
.append(value)
.append("</li>")
.append("\n"));

content.append("<br>").append("\n");
});

continue;
}

content.append(line).append("\n");
}
} catch (IOException e) {
throw new RuntimeException(e);
}

return content.toString();
}

private String getViewPath(final HttpServletRequest req) {
final ServletContext sc = req.getServletContext();
return sc.getRealPath(viewName);
}
}
10 changes: 10 additions & 0 deletions src/main/java/com/diy/framework/web/mvc/view/HtmlViewResolver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.diy.framework.web.mvc.view;

public class HtmlViewResolver implements ViewResolver {

@Override
public View resolveViewName(final String viewName) {
final String resolvedViewName = "/templates/" + viewName + ".html";
return new HtmlView(resolvedViewName);
}
}
26 changes: 26 additions & 0 deletions src/main/java/com/diy/framework/web/mvc/view/JspView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.diy.framework.web.mvc.view;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

public class JspView implements View {
private final String viewName;

public JspView(final String viewName) {
this.viewName = viewName;
}

@Override
public void render(final Map<String, ?> model, final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException {
for (final Map.Entry<String, ?> entry : model.entrySet()) {
req.setAttribute(entry.getKey(), entry.getValue());
}

final RequestDispatcher requestDispatcher = req.getRequestDispatcher(viewName);
requestDispatcher.forward(req, res);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.diy.framework.web.mvc.view;

public class JspViewResolver implements ViewResolver {

@Override
public View resolveViewName(final String viewName) {
return new JspView("/" + viewName + ".jsp");
}
}
27 changes: 27 additions & 0 deletions src/main/java/com/diy/framework/web/mvc/view/ModelAndView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.diy.framework.web.mvc.view;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class ModelAndView {
private final String viewName;
private final Map<String, Object> model = new HashMap<>();

public ModelAndView(final String viewName) {
this.viewName = viewName;
}

public ModelAndView(final String viewName, final Map<String, Object> model) {
this.viewName = viewName;
this.model.putAll(model);
}

public String getViewName() {
return viewName;
}

public Map<String, Object> getModel() {
return Collections.unmodifiableMap(this.model);
}
}
19 changes: 19 additions & 0 deletions src/main/java/com/diy/framework/web/mvc/view/RedirectView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.diy.framework.web.mvc.view;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

public class RedirectView implements View {

private final String redirectUrl;

public RedirectView(final String redirectUrl) {
this.redirectUrl = redirectUrl;
}

@Override
public void render(final Map<String, ?> model, final HttpServletRequest req, final HttpServletResponse res) throws Exception {
res.sendRedirect(redirectUrl);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.diy.framework.web.mvc.view;

public class UrlBasedViewResolver implements ViewResolver {
@Override
public View resolveViewName(final String viewName) {
if (!viewName.startsWith("redirect:")) {
return null;
}

final String redirectUrl = viewName.substring("redirect:".length());
return new RedirectView(redirectUrl);
}
}
Loading