Spring Boot QuickStart (3) - Web & Restful

Keywords: Java Session Spring Thymeleaf REST

Spring Boot QuickStart (3) - Web & Restful

Environment: Spring Boot 1.5.4

Spring Boot allows you to quickly create a Web & Restful application. At least before you start using Spring Boot, you need to understand the following usages:

  • Define routing, define HTTP methods

  • Get parameters such as Header, GET, POST, path, etc.

  • Cookie, Session operation

  • Apply a template engine and select Thymeleaf

  • Get form data and file upload data

  • Complete a login, login, registration process

Add the following two dependencies to complete the build:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Note: The current version of Thymeleaf is 2.x by default, which requires high closeness of html tags. Although mode can be set to change the parsing mode, additional Neko html will be introduced, so it is very painful. However, it can be switched to version 3.x with unknown compatibility.

<properties>
    <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
    <thymeleaf-layout-dialect.version>2.1.1</thymeleaf-layout-dialect.version>
</properties>

annotation

Once spring-boot-starter-web dependency Spring Boot is added, it determines that it is a Web application and starts an embedded Servlet container (Tomcat by default) to process HTTP requests.

There are a lot of annotations about Web applications in the Spring framework:

@Controller
Annotate a Web Controller class, and the framework distributes HTTP requests received in the Servlet container to the corresponding Controller class for processing according to the path

@RestController
Annotate a Restful Controller, which automatically returns to JSON by default

@RequestMapping
Annotate a routing, if defined on a class, which is equivalent to a routing group. The final routing is class + method routing. The parameters are routing rules and HTTP methods. There are also some abbreviations such as @GetMapping,@PutMapping.

@PathVariable
Annotate path parameters, such as / user/{id}

@RequestParam
Annotation request parameters, such as? user=a or post['user'] = a

@RequestBody
Annotation Request Body

@RequestHeader
Annotation request header header

@CookieValue
Annotate a Cookie value

@SessionAttribute
Annotate a Session value

Routing, Method

The following code corresponds to two routes:

/ With the @ResponseBody annotation, the text string is returned
/ Hello returns the string representing the template, which will be rendered using resources/templates/hello.html template

@Controller
public class IndexController {

    @RequestMapping("/")
    @ResponseBody
    public String index() {
        return "Spring Boot Index";
    }

    @RequestMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("title", "Spring Boot");
        return "hello";
    }
}

This code corresponds to / rest / routing. Note the difference between @RequestMapping hollow strings and'/'.
Using empty, then / rest and / rest / can be accessed, and using / then must be accessed through / rest:

@RestController
@RequestMapping("/rest")
public class RestfulController {

    @RequestMapping("")
    public String index() {
        return "Hello Rest";
    }
}    

hello.html:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title th:text="'Hello, ' + ${title}">title</title>
</head>
<body>
<h1 th:text="'Hello, ' + ${title}">h1</h1>
</body>
</html>

Request parameters

Single parameter

RequestParam can be used to annotate a request parameter. By default, GET and POST request names are merged into an array, so the following text 2 will be transformed into an array - > String.

@RequestMapping(value = "/get", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public String get(@RequestParam("text1") String text1, @RequestParam("text2") String text2) {

   return text1 + "/" + text2;
}

Data can also be obtained without annotations here, so why use annotations? Because @RequestParam mainly provides some additional functions:
For example, the mapping of parameter name - > variable name, required check, etc., is more rigorous.

@RequestMapping(value = "/getsimple", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public String getSimple(String text1, String text2) {
   return text1 + "/" + text2;
}

parameter list

In addition to using the @RequestParam annotation to get a single parameter unexpectedly, you can also get a list of parameters, but in this way, POST does not merge the same name parameters in GET:

@RequestMapping("/getmap")
@ResponseBody
public String getMap(@RequestParam Map<String, Object> gets) {
   return gets.toString();
}

List of additional parameters

In addition to annotations to get data, we can also get additional parameters, such as client IP addresses, by injecting Servlet-related classes into methods in Controller

@RequestMapping("/request")
@ResponseBody
public String request(HttpServletRequest request) {
   HashMap<String, String> requests = new HashMap<>();

   requests.put("Method", request.getMethod());
   requests.put("QueryString", request.getQueryString());
   requests.put("RequestURI", request.getRequestURI());
   requests.put("getRequestURL", request.getRequestURL().toString());
   requests.put("RemoteAddr", request.getRemoteAddr());

   return requests.toString();
}

Cookie

Cookie's operation doesn't really have much to do with Spring, but Spring provides an @CookieValue annotation to quickly retrieve Cookie values.

Set up the Cookie of the page through HttpServletResponse:

@RequestMapping("/setcookie")
@ResponseBody
public String setCookie(HttpServletResponse response) {
   Cookie cookie1 = new Cookie("cookie1", "value1");
   cookie1.setMaxAge(1800);
   Cookie cookie2 = new Cookie("cookie2", "value2");
   cookie2.setMaxAge(3600);

   response.addCookie(cookie1);
   response.addCookie(cookie2);
   return "cookie set ok";
}

Get Cookie by HttpServletRequest or @CookieValue annotation:

@RequestMapping("/getcookie")
@ResponseBody
public String getCookie(HttpServletRequest request,
       @CookieValue(value = "cookie1", required = false) String cookie1) {

   HashMap<String, String> map = new HashMap<>();
   Cookie[] cookies = request.getCookies();
   if (cookies != null) {
       for (Cookie cookie : cookies) {
           map.put(cookie.getName(), cookie.getValue());
       }
   }

   logger.info(cookie1);

   return map.toString();
}

Clearing the cookie means resetting the value and expiration time of the cookie:

@RequestMapping("/delcookie")
@ResponseBody
public String delCookie(HttpServletRequest request, HttpServletResponse response) {
   Cookie[] cookies = request.getCookies();
   if (cookies != null) {
       for (Cookie cookie : cookies) {
           // setValue just empties the value, cookie is still there
           cookie.setValue(null);
           cookie.setMaxAge(0);
           response.addCookie(cookie);
       }
   }

   return "delete ok";
}

Session

Session-related operations are accomplished through HttpSession, HttpServletRequest, @Session Attribute.

Set Session:

@RequestMapping("/setsession")
@ResponseBody
public String setSession(HttpSession session) {
   session.setAttribute("session1", "value1");
   session.setAttribute("session2", "value2");
   return "";
}

Get Session:

@RequestMapping("/getsession")
@ResponseBody
public String getSession(
       HttpServletRequest request,
       HttpSession httpSession,
       @SessionAttribute(value = "session1", required = false) String session1) {
   HttpSession session = request.getSession();
   String session2 = (String)session.getAttribute("session2");
   String http_session1 = (String)httpSession.getAttribute("session1");

   logger.info(http_session1);
   logger.info(session1);
   logger.info(session2);

   HashMap<String, String> sessionMap = new HashMap<>();
   Enumeration<String> sessions = session.getAttributeNames();
   while(sessions.hasMoreElements()) {
       String key = sessions.nextElement();
       sessionMap.put(key, (String)session.getAttribute(key));
   }

   return sessionMap.toString();
}

Delete Session:

@RequestMapping("/delsession")
@ResponseBody
public String delSession(HttpSession httpSession) {
   httpSession.removeAttribute("session1");
   httpSession.removeAttribute("session2");

   return "delete session ok";
}

template engine

Before the template engine, to understand how to transfer data to the template, there are three positions:

Map, which is a native Java type
 ModelMap, which is a class
 Model, an interface whose implementation class is Extended ModelMap, inherits the ModelMap class

These three can be directly injected into the method parameters. I don't know the difference between them for the time being. They are almost the same.

@RequestMapping("/model")
public String model(Model model, ModelMap modelMap, Map<String, Object> map) {
   model.addAttribute("title1", "model_title");
   modelMap.addAttribute("title2", "modelMap_title");
   map.put("title2", "map_title");

   User user = new User(1, "test");
   model.addAttribute("user", user);

   return "model";
}

In addition to the above usage, you can use ModelAndView to render templates manually. The effect is the same:

@RequestMapping("/modelandview")
public ModelAndView modelAndView() {
   ModelAndView modelAndView = new ModelAndView();
   modelAndView.setViewName("model");
   modelAndView.addObject("title1", "title1");
   modelAndView.addObject("title2", "title2");

   User user = new User(1, "test");
   modelAndView.addObject("user", user);

   return modelAndView;
}

Finally, SpringBook can integrate several template engines by default, and now mainly uses thymeleaf.

The @ModelAttribute annotation

This annotation is a bit complicated. It can be annotated to a method or to a method parameter.

  1. Annotation to method parameters

Maybe it's got through the model. What's the model? Probably through a number of ways (probably from Session? Maybe from request parameters? Maybe @ModelAttribute annotated from the controller to the method

Complete automatic filling, and automatically pass to the template, which is Spring MVC data binding.

Here are two examples:

Requests can be automatically mapped through / xxx? Id = 1 & name = Zhang San, and passed to the template, and can also automatically convert the output format. As the first example below, influenced by @ResponseBody, JSON is directly output.

@RequestMapping("/getmodel")
@ResponseBody
public User getModel(@ModelAttribute User user) {
   return user;
}

@RequestMapping("/modelattribute")
public String modelAttribute(@ModelAttribute User user) {
   return "model";
}
  1. Annotation to Method

The method of this controller is transformed into a non-request processing method, which is called first before other request methods (Request Mapping) are invoked, and the returned data is put into the Model.

What's the use?

Estimates are used to generate initialization data, such as a form with some default data? Do some data cleaning before entering the controller?

Common configuration

Automatic trim parameters

Most PHP frameworks have automatic trim GET/POST parameters

In Spring, this can be done with the @InitBinder annotation. We define a controller base class to facilitate the acceptance of the request for controller inheritance.

public class BaseController {
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        StringTrimmerEditor stringtrimmer = new StringTrimmerEditor(true);
        binder.registerCustomEditor(String.class, stringtrimmer);
    }
}

server

server.address binding address
server.port Binding Port
Does server.compression.enabled turn on compression
Types of server.compression.mime-types compression
Threshold of server.compression.min-response-size compression

server.tomcat.* access log, log directory, number of threads, etc.

server.session.cookie.* SessionCookie related configuration

Posted by bri4n on Tue, 01 Jan 2019 03:51:08 -0800