Spring MVC Basic Knowledge
- Web Application Server WAS
-
includes Web server functionalites and static resource managing
-
Difference between web server and WAS is web server is mainly for static resource while WAS can have application logic
-
Servlet does all except business logic
-
Contact switching cost is when CPU switches between its threads to do tasks.
-
WAS takes care of multi-threading so we developers no need care code about multi-threading
-
Server Side Rendering SSR - generates and renders final HTML page and delivers to client
-
Client Side Rendering CSR - front-end
-
View Template - generates HTML easily
-
- Servlet
-
In resources -> application.properties -> logging.level.org.apache.coyote.http11=debug this helps debugging much better but only in developmenmt server, not actual server cuz it will decrease performance
-
Ctrl + O and select service method with lock sign on it for HttpServlet
-
HTTP메소드에서 GET방식은 value=text 형식으로 보내지고 body가 없기 떄문에 Content-Type은 필요없다. HTTP메소드에 POST, PUT처럼 Body에 data를 보낼때 Content-Type이 필요하다. Content-type describes what kind of data is in body for humans to easily understand.
-
request.getParameterNames gets the key(paramName) while request.getParameter(paramName) gets the value of the key
-
Lombok library implements getter and setter automatically. We just need to add @Getter @Setter on top of the class
-
Instead of directly setting the response erro code by resp.setStatus(200); it is better to resp.setStatus(HttpServletResponse.SC_OK)
-
-
Servlet, JSP, MVC
- Declare singleton
private static final MemberRepository instance = new MemberRepository();
- Then, create a private constructor to prevent making new instances of it
private MemberRepository() { }
- Lastly, create method getInstance() that always return this singleton instance
private static MemberRepository getInstance(){ return instance; }
-
Once it is singleton, cannot create another instance of it via MemberRepository memberRepository = new MemberRepository(), we should call the already-made single instance via MemberRepository memberRepository = MemberRepository.getInstance()
-
@AfterEach resets whatever test has done to variable after each test for the next test to be done on that variable
-
ol element in HTML lists items with numbers (ordered) like 1,2,3, but ul element lists items with just bullet points (unordered)
-
If status code is grey instead of black, it means it is cached
-
In MVC, Controller(controller logic) is like servlet , View(View logic) is like JSP and Service/Repository does business logic and data
-
Very Important It is the controller that calls the view like
@WebServlet(name="mvcMemberFormServlet",urlPatterns = "/servlet-mvc/members/new-form") public class MvcMemberFormServlet extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String viewPath = "/WEB-INF/views/new-form.jsp"; RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath); dispatcher.forward(request,response); } }
-
In JSP, if action=”/save”, (절대경로 absolute path, better than relative path) URL is localhost:8080/save but if it is action=”save”, (상대경로 relative path) it starts from current directory localhost:8080/servlet-mvc/members/save from localhost:8080/servlet-mvc/members/new-form.jsp
-
/WEB-INF restricts external calling, resource under /WEB-INF always goes through Controller and cannot be called externally like going to URL/some-resource.html <- this is not allowed
-
서블릿을 컨트롤러로 사용하고, JSP를 뷰로 사용해서 MVC 패턴을 적용해보자. Model은 HttpServletRequest 객체를 사용한다. request는 내부에 데이터 저장소를 가지고 있는데, request.setAttribute() , request.getAttribute() 를 사용하면 데이터를 보관하고, 조회할 수 있다.
-
Instead of saving user variables in request.setAttribute(), store them in a model
-
Since handler is object to be flexibly used in v5 MVC pattern, cast it to a different type via (ControllerV3) handler;
-
either @Controller or @Component with @RequestMapping works
-
Instead of @RequestMapping(value=”/new-form”,method= RequestMethod.GET), do @GetMapping(“/new-form”)
-
@Controller returns View so cannot directly return string but @RestController returns whatever the method type returns like string and inputs directly into HTTP message. Or use @ResponseBody that puts it straight into HTTP message body
@GetMapping("/mapping/{userId}") public String mappingPath(@PathVariable("userId") String data){ // public String mappingPath(@PathVariable String userId) <- if variable name is same as @PathVariable log.info("mappingPaath userId ={}", data); return "ok"; }
-
MultiValueMap is when a key gets several values
-
For @RequestParam(required = false) int age, Integer is object so can be null bunt int cannot be null. SO correct code is @RequestParam(required = false) Integer age. Primitive type (int). Different for @ModelAttribute so search up
-
For @ModelAttribute HelloData helloData, if the object has methods like getUsername(), it has username property.
-
@RequestBody Hellodata hellodata <-cant put your already-made object
-
can add @ResponseBody at the public class level, which adds @ResponseBody for all the classes inside it. ResponseEntity is not affected but there are few tricky exceptions. So just use @RestController, which adds @ResponseBody and @Controlelr together
-
Webpage
-
In multi-thread environment, cannot use HashMap, use ConcurrentHashMap. cannot use long sequence, use automic long? sequence
-
2 ways to view static content: either copy absolute path of that html file and google without running server or run server and go to that file location via localhost:etc
-
Only GET and not POST works for viewing static content?
-
@Autowired, which is for Dependency injection, can be omitted if there is only 1 constructor
-
@RequiredArgsConstructor substitutes need to write constructor
-
for th:action=”some_url”, the url can be omitted and it is nesured that url method is POST
-
@ModelAttribute(“item”) Item item automatically adds attribute so no need to add this line model.addAttribute(“item”, item);
-
If no name is assigned with @ModelAttribute, it automatically takes the class that it is going to create object with and make it lowercase and name it like Item -> item or HelloData -> helloData
-
HTTP session is maintaing user’s details until he quits the browser but HTTP request deletes details once that request has been fulfilled
-
th:field= “${item.itemName}” automatates declaration of id=”itemName” name=”itemName” so can delete that
-
hidden field to prevent open from coming out null -> input type=”hidden” name=”_open” value=”_on”/
-
LinkedHashMap guarantees 순서 in which stuff go in, unlike HashMap
-
when naming stuff to be called by Thymeleaf, be careful (e.g. “regions” instead of “region”)
-
th:object=”${item}” so th:field=”*{regions} means item.regions. This th:object can be very far away in form tag and asterisk * can only be used if there is th:object
-
no hidden field needed for radio button, unlike checkbox
-
Even when invalid field for price/quantity is POSTed for new item, parameter for addItem - @ModelAttribute Item item autoamtically adds model.addAttribute(“item”,item) so when redirected, we can see item’s saved variables
-
no need to add bindingResult to model attribute because it is automatically added to view
-
bindingResult.rejectValue(“price”,”range”); the error message “range” follows range.item.price where bindingResult’s object type is item. MessageCodeResolver?
-
WebDataBinder works for that specific controller via boolean supports that checks class
-
@ModelAttribute(“item”) ItemUpdateForm form <-must name it as “item” because template uses “item” and if it is not renamed manually, model.addAttribute(“itemUpdateForm”,item) is done instead of model.addAttribute(“item”,item) so does not render properly unless u change th:object in thymeleaf
-
@RestController automatically adds @ResponseBody so it converts whatever to JSON
- @ModelAttribute 는 HTTP 요청 파라미터(URL 쿼리 스트링, POST Form)를 다룰 때 사용한다.@RequestBody 는 HTTP Body의 데이터를 객체로 변환할때 사용한다. 주로 API JSON 요청을 다룰 때 사용한다
List<Member> all = findAll(); for (Member member : all) { if(member.getLoginId().equals(loginId)){ return Optional.of(member); } } return Optional.empty(); <!-- is same as this stream --> return findAll().stream() .filter(member -> member.getLoginId().equals(loginId)) .findFirst();
-
@ModelAttribute(“member”) Member member <- no need to name it “member” cuz ModelAttribute automatically takes lowercase of Member object but in Thymeleaf, IDE sometimes does not detect it so name like this for now
-
Another example:
public Member login(String loginId, String password){ Optional<Member> findMemberOptional = memberRepository.findByLoginId(loginId); Member member = findMemberOptional.get(); if(member.getPassword().equals(password)){ return member; } else { return null; } return memberRepository.findByLoginId(loginId). filter(m -> m.getPassword().equals(password)) .orElse(null);
-
If no time info ias added to cookie, that cookie becomes session cookie which disappears upon browser exit
-
When there are multiple requests at same time, use ConcurrentHashMap
-
request.getCookies are returned as an array so Cookie[] cookies = request.getCookies();
-
For @RequestMapping, we use HandlerMethod but for static resource, use ResourceHttpRequestHandler
-
log.error does not need “{}”, just “ whatever message”
-
Interceptor cannot set dispatcher type like filter but can include path route in excludePathPatterns
-
use ObjectMapper to convert to JSON for ModelAndView
-
server.error.include-message=always to customise error messages
-
for @ModelAttribute Form form, no need to model.addAttribute cuz automatically added (check this again but it is true)
-