preface

Spring day learning outline:

  1. Advanced Parameter binding
    1. Parameter binding of array type
    2. List binding
  2. Use of @requestMapping annotations
  3. The Controller method returns the value
  4. Exception handling in SpringMVC
  5. Image upload processing
  6. Json data interaction
  7. For SpringMVC implement Restful
  8. The interceptor

1. Advanced parameter binding

1.1 Binding an Array

Requirement: Select multiple items on the item list page and delete them.

Requirement analysis: This function requires that there is a checkbook before each commodity in the commodity list page. After selecting multiple commodities, click the delete button to transfer the commodity ID to the Controller and delete the commodity information according to the commodity ID.

JSP implementation:

<c:forEach items="${itemList }" var="item"> <tr> <! <td><input name="ids" value="${item.id}" type="checkbox"></ TD >< TD >${item.name}</td> <td>${item.price }</td> <td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td> < td > ${item. Detail} < / td > < td > < a href = "${pageContext. Request. ContextPath} / itemEdit action? Id = ${item. Id}" > change < / a > < / td > </tr> </c:forEach>Copy the code

QueryVo. Java is as follows:

It can be received with String[] in the Controller method, or with the String[] property of the POJO. You can do it either way. The definition is as follows:

@RequestMapping("/delAll")
public String delAll(QueryVo vo) throws Exception{
    // The array can be submitted if the input check box is selected.
    System.out.println(vo);
    return "";
}
Copy the code

1.2 Bind the form’s data to the List

Requirement: to achieve batch modification of commodity data.

Requirement analysis: In order to achieve batch modification of commodity data, the commodity information can be modified in the commodity list and the modified commodity data can be submitted in batches.

Pojos for receiving List of goods: The List holds objects, and the defined List is placed in the wrapper class, which is received using the wrapper POJO object.

The page definition is as follows:

<c:forEach items="${itemList }" var="item" varStatus="status"> <tr> <td> <input type="checkbox" name="ids" value="${item.id }"/> <input type="hidden" name="itemsList[${status.index }].id" value="${item.id }"/> </td> <td><input type="text" name="itemsList[${status.index }].name" value="${item.name }"/></td> <td><input type="text" name="itemsList[${status.index }].price" value="${item.price }"/></td> <td><input type="text" name="itemsList[${status.index }].createtime" value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td> <td><input type="text" name="itemsList[${status.index }].detail" value="${item.detail }"/></td> < td > < a href = "${pageContext. Request. ContextPath} / itemEdit action? Id = ${item. Id}" > change < / a > < / td > < / tr > < / c: forEach >Copy the code

Common parameters of varStatus attribute are summarized as follows:

${status.index} prints the line number, starting with 0.

${status.count} prints the line number, starting with 1.

${status.current} is the entry of the current iteration

${status.first} determines whether the current item is the first item in the collection and returns true or false

${status.last} determines whether the current item is the last item in the collection and returns true or false

Begin, end, and step indicate the start sequence number, end sequence number, and jump step respectively.

Batch update test:

@RequestMapping("/updateAll")
public String updateAll(QueryVo vo) throws Exception{
    System.out.println(vo);
    return "";
}
Copy the code

Note: Receiving data of type List must be a poJO property. Methods with parameters of type List cannot receive data correctly.

Add: The variable name of the parameter received by the Controller method must be equal to the value of the name property in the input box on the page.

The Controller methods:

But you can also use @RequestParam(” “) so that the name of the input box property is not required to be equal to the name of the POJO property.

Use of @requestMapping annotations

RequestMapping annotations allow you to define different processor mapping rules.

Dynamic URL Path Mapping:

@ RequestMapping (value = "/ item") or @ RequestMapping ("/item)

The value of value is an array that maps multiple urls to the same method.

Narrow Request Mapping:

Add @requestMapping (URL) to the class to specify a universal request prefix to restrict all url requests in this class to start with the request prefix and manage urls by category. As follows:

Put @requestMapping above the class name and set the request prefix:

@Controller
// Narrow request mapping: To prevent you and your teammates from having the same name in the Conroller method, add a layer of directories in the URL to prevent the same name
// For example, access path of the current list localhost:8081/ sSM0523-1 /items/list.action
@RequestMapping("/items")
public class ItemsController {}Copy the code

Set the request mapping URL above the method name:

RequestMapping is placed above the method name as follows:

@Controller
@RequestMapping("/items")
public class ItemsController {
    @RequestMapping("/list")
    public ModelAndView itemsList(a) throws Exception{}}Copy the code

Visit address:… /items/list

Request Method Limit:

  1. @requestMapping (method = requestmethod.get);

    HTTP Status 405 – Request method ‘POST’ not supported

    For example: @ RequestMapping (value = “/ editItem”, method = RequestMethod. GET)

  2. @requestMapping (method = requestmethod.post);

    HTTP Status 405 – Request method ‘GET’ not supported

  3. The GET and POST are: @ RequestMapping (method = {RequestMethod. GET RequestMethod. POST})

The Controller method returns a value

Dynamic Return to ModeAndView:

The Controller method defines and returns a ModelAndView object to which model data can be added and the view specified.

New Year returns void:

Request and Response can be defined on the controller method parameter, using request or Response to specify the result of the response:

1. Redirect to the page using Request as follows:

// Specify the page to return (if the Controller method returns void, the springMvc component is not used, so write the full path name of the page)
request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request, response);
Copy the code

2. You can also redirect through the Response page:

// Redirect: The url in the browser has changed, and the data in the request field cannot be carried to the redirected method
response.sendRedirect("url")
Copy the code

3. You can also specify the response result by response. For example, the response JSON data is as follows:

response.setCharacterEncoding("utf-8");
response.setContentType("application/json; charset=utf-8");
response.getWriter().write("The json string");
Copy the code

Dynamic Returns a string:

  • Logical view name: The Controller method returns a string that specifies the logical view name, which is parsed by the view parser into the physical view address.

    / / specify the logical view, after view the parser resolves to the JSP physical path: / WEB - INF/JSP/items/editItem JSP
    return "items/editItem";
    Copy the code
  • Redirect: The results returned by the Contrller method are redirected to a URL as shown in the following figure. After the product modification is submitted, the parameters are redirected to the product query method.

    // Redirect to queryItem.action,request cannot be taken
    return "redirect:queryItem.action"; // In springMvc, anything that starts with redirect: is redirected
    Copy the code

    Redirect is response.sendreDirect (). After forwarding, the browser address bar changes to the forwarded address because forwarding executes a new Request and response. If a request is initiated, the original parameters cannot be forwarded to the next URL. If you want to send parameters, you can add parameters after /items/ queryitem. action, for example: /items/queryItem? . &… .

  • Forward: After the Controller method is executed, the other Controller method is executed. After the following product modification is submitted, the product modification page is displayed. The id parameter of the modified product can be added to the product modification method.

    // The result is forwarded to edititem. action, which request can take with it
    return "forward:itemEdit.action"; // Request forward in spirngMvc: returns a string starting with forward: that is request forward
    Copy the code

    Way forward is equivalent to the request. GetRequestDispatcher (). The forward (request, response), after forwarding your browser’s address bar or the original address. Forwarding does not execute new request and response, but shares the same request and response with the request before forwarding, so the parameters of the request before forwarding can still be read after forwarding.

    Note: ① Forward: ItemEdit. action indicates the relative path. The relative path is the items directory specified in the class relative to the current directory.

    ② Forward :/ itemedit. action Specifies the absolute path starting with a slash. The absolute path starts after the item name.

Exception handlers

1. Idea of exception handling

SpringMVC sends abnormal information to the exception processor for processing in the process of processing requests. Custom exception processor can realize the exception processing logic of a system.

Exceptions in the system include two types: expected exceptions and runtimeexceptions. The former captures exceptions to obtain exception information, and the latter reduces the occurrence of run-time exceptions by means of standard code development and testing.

Dao, Service, and controller of the system are thrown upward through throwsException, and finally handed over to exception processor by SpringMVC front-end controller for exception processing.

2. Custom exception classes

In order to distinguish different exceptions, we usually define the exception class according to the exception type. Here, we create a custom system exception. If the Controller, Service, or DAO throws such exception information, it indicates that the system expects to handle the exception information.

// Custom exception class, used to handle custom exceptions
public class CustomException extends Exception {
    private static final long serialVersionUID = -5212079010855161498L;

    public CustomException(String message){
        super(message);
        this.message = message;
    }
    // Exception information
    private String message;
    public String getMessage(a) {
        return message;
    }
    public void setMessage(String message) {
        this.message = message; }}Copy the code

3. Custom exception handlers

public class CustomExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        ex.printStackTrace();
        CustomException customException = null;

        // If a system - defined exception is thrown, it is directly converted
        if(ex instanceof CustomException){
            customException = (CustomException)ex;
        }else{
            // If it does not throw a system custom exception, reconstruct a system error exception.
            customException = new CustomException("System error, please contact your system administrator!");
        }

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("message", customException.getMessage());
        modelAndView.setViewName("error");
        returnmodelAndView; }}Copy the code

4. Error page

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <! PUBLIC DOCTYPE HTML "- / / / / W3C DTD HTML 4.01 Transitional / / EN" "http://www.w3.org/TR/html4/loose.dtd" > < HTML > < head > < meta  http-equiv="Content-Type" content="text/html; <br/> ${message} </body> </ HTML >Copy the code

5. Exception handler configuration

Add to SpringMvc. XML:

<! -- Exception handler -->
<bean id="handlerExceptionResolver" class="cn.itheima.exception.CustomExceptionResolver"/>
Copy the code

6. Exception testing

Description When modifying the product information, an incorrect id is entered, indicating that the product information does not exist.

Modify the Controller method itemEdit and call service to query the item information. If the item information is empty, raise an exception:

// Call service to query commodity information
Items item = itemService.findItemById(id);
if(item == null) {throw new CustomException("Product information does not exist!");
}
Copy the code

Upload pictures

Generally uploaded pictures are not uploaded to the local machine, but uploaded to a picture server, general Internet enterprises are to arrange clusters, and this picture server is specifically used to put pictures.

We don’t have a separate server right now, but we can demonstrate by creating a virtual picture server. How? –> Use Tomcat.

1. Configure a virtual directory

In conf/server. XML of tomcat, add:

<Context docBase="F:\develop\upload\temp" path="/pic" reloadable="false"/>
Copy the code

Visit http://localhost:8080/pic to access F: \ develop \ upload \ temp folder.

You can also configure it through Eclipse:

Enctype =”multipart/form-data” encType =”multipart/form-data”

Once uploaded from the page, it is in the form of a stream, so we need to parse the uploaded content. Therefore, the relevant JAR packages need to be imported.

PS: CommonsMultipartResolver depends on commons-fileupload and commons-io.

3, configure the parser, add to the SpringMvc. XML file:

<! -- File upload -->
<bean id="multipartResolver"
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <! -- Set the maximum size of uploaded files to 5MB -->
    <property name="maxUploadSize">
        <value>5242880</value>
    </property>
</bean>
Copy the code

4. Picture uploading, Controller:

public String update(MultipartFile pictureFile,Items items, Model model, HttpServletRequest request) throws Exception{
    //1. Get the full name of the image
    String fileStr = pictureFile.getOriginalFilename();
    //2. Use a randomly generated string + the extension of the source image to form a new image name to prevent the same image name
    String newfileName = UUID.randomUUID().toString() + fileStr.substring(fileStr.lastIndexOf("."));
    //3. Save the image to the hard disk
    pictureFile.transferTo(new File("F:\\develop\\upload\\temp" + newfileName));
    //4. Save the image name to the databaseitems.setPic(newfileName); itmesService.updateItems(items); .Copy the code

Page:

<! Enctype = is required for uploading images"multipart/form-data" -->
<form id="itemForm" action="${pageContext.request.contextPath }/item/editItemSubmit.action" method="post" enctype="multipart/form-data">
    <input type="hidden" name="pic" value="${item.pic }" />

Copy the code

The name of file is the same as the controller parameter:

<tr> <td><c:if test="${item.pic! =null}"> <img src="/pic/${item.pic}" width=100 height=100 /> <br /> </c:if> <input type="file" name="pictureFile" /></td> </tr>Copy the code

Summary of steps:

1) Configure the virtual image server in Tomcat 2) import the JAR package of Fileupload 3) configure the upload component in springMVC.xml 4) write the upload domain on the page and change the type of the form label 6) Save the file name to the database and save the image to diskCopy the code

6. Json data interaction

☛ @ RequestBody

The @RequestBody annotation is used to read the content (string) of the HTTP request, The HttpMessageConverter interface provided by SpringMVC converts the read content into json, XML, and other data and binds it to the parameters of the Controller method.

Application of this example: the @RequestBody annotation accepts JSON data from an HTTP request and converts it into a Java object

List.action? id=1&name=zhangsan&age=12
Copy the code

☛ @ ResponseBody

Function: This annotation is used to convert the object returned by the Controller method into data in the specified format, such as JSON, XML, etc., via the HttpMessageConverter interface, and send the response to the client.

Application of this example: the @responseBody annotation converts the controller method return object into a JSON response to the client

fdaf
Copy the code

Case: Request JSON, Response JSON implementation

Preparation: (1) environment for SpringMVC default MappingJacksonHttpMessageConverter are used to characterize the json data conversion, need to join the Jackson’s package, are as follows:

2. Configure the JSON converter. Add messageConverters to the annotation adapter in the SpringMVC configuration file

<! -- Annotation adapter -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
        </list>
    </property>
</bean>
Copy the code

Note however: if you use < MVC :annotation-driven /> you don’t have to define this.

(3) the controller to write

You can use @requestBody in the Controller method to get spirngMvc to automatically convert jSON-formatted strings to Java POJOs
// The page JSON key should be equal to the property name of the Java POJO
// The Controller method returns an object of type POJO and with the @responseBody annotation,springMvc automatically converts the POJO object to a JSONformat string
@RequestMapping("/sendJson")
@ResponseBody
public Items json(@RequestBody Items items) throws Exception{
    System.out.println(items);
    return items;
}
Copy the code

(4) Page JS writing

<script type="text/javascript"> function sendJson(){// request json response json $. Ajax ({type:"post", url:"${pageContext.request.contextPath }/items/sendJson.action", contentType:"application/json; Charset = utf-8 ", data: '{" name ":" test items ", "price" : 99.9}', success: function (data) {alert (data); }}); } </script>Copy the code

Debugging result:

RESTful support

1. What is restful?

Restful is a style of locating and operating resources. It is not a standard or a protocol, but a style, an interpretation of the HTTP protocol.

Resource location: All things on the Internet are resources, requiring urls with no verbs, only nouns, and no parameters

  • Such as:http://blog.csdn.net/beat_the_world/article/details/45621673

Resource operations: Use put, DELETE, POST, and GET to perform operations on resources. Corresponding to add, delete, modify, query. Post and GET are commonly used. Put and DELETE are rarely used.

2. Learn by case study

Requirements: RESTful way to achieve product information query, return JSON data

Add rest configuration of DispatcherServlet, web.xml:

<! -- SpringMVC front-end Controller -->
<servlet>
    <servlet-name>springMvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:SpringMvc.xml</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>springMvc</servlet-name>
    <! Action intercepts all but not.jsp /* Intercepts all including.jsp -->
    <url-pattern>/</url-pattern>
</servlet-mapping>
Copy the code

② URL template mode mapping

@ RequestMapping (value = “/ viewItems / {id}”) : {×××} placeholder, the requested URL can be “/viewItems/1” or “/viewItems/2”, by using @pathVariable in the method to get the ××× variable in {×××}.

@pathVariable: Used to map template variables in the request URL to parameters of the function handling method.

* @requestMapping ("/itemEdit/{id}"); The variable name in @pathVariable must be the same as the variable name in RequestMapping */
@RequestMapping("/itemEdit/{id}")
public String itemEdit(@PathVariable("id") Integer id, HttpServletRequest reuqest, 
                       Model model) throws Exception{
    Items items = itmesService.findItemsById(id);
    model.addAttribute("item", items);
    return "editItem";
}
Copy the code

Page definition:

< td > < a href = "${pageContext. Request. ContextPath} / items/itemEdit / ${item. Id}" > change < / a > < / td >Copy the code

Note: For redirection, the url in the browser has been changed, and the data in the request field cannot be carried to the redirected method, but in a restful manner, as follows:

return "redirect:itemEdit/"+items.getId();
Copy the code

You can take this back. This method is in the form of a URL string, not a request domain thing.

8. Interceptor

8.1 Interceptor learning

Spring Web MVC’s processor interceptor is similar to the Filter used in Servlet development for pre-processing and post-processing of the processor.

SpringMVC interceptor flowchart:

The HandlerInterceptor interface is the same as the HandlerInterceptor interface.

public class Interceptor1 implements HandlerInterceptor {

    // Execution time: Controller already executed,modelAndview already returned
    // Operation logs record the IP addresses and time of login users.
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
        throws Exception {
        System.out.println("======Interceptor1=======afterCompletion========");
    }

    // Execution time: The Controller method was executed,ModelAndView did not return
    // Use scenario: You can set the global data processing service in this method
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
        throws Exception {
        System.out.println("======Interceptor1=======postHandle========");

    }

    // Return Boolean: if true is allowed, false is blocked
    // Execution timing: Controller method not executed,ModelAndView not returned
    // Application scenario: Permission verification
    @Override
    public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
        System.out.println("======Interceptor1=======preHandle========");
        return true; }}Copy the code

Add interceptor to SpringMvc. XML file:

<! -- Configure interceptor -->
<mvc:interceptors>
    <mvc:interceptor>
        <! -- Intercept request path to intercept all the necessary configuration to /** -->
        <mvc:mapping path="/ * *"/>
        <! -- Specify interceptor location -->
        <bean class="cn.itheima.interceptor.Interceptor1"></bean>
    </mvc:interceptor>
</mvc:interceptors>
Copy the code

Running results:

8.2 Execution sequence of multiple interceptors

Define two interceptors as HandlerInterceptor1 and HandlerInterceptor2

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/ * *"/>
        <bean class="cn.itheima.interceptor.HandlerInterceptor1"></bean>
    </mvc:interceptor>
     <mvc:interceptor>
        <mvc:mapping path="/ * *"/>
        <bean class="cn.itheima.interceptor.HandlerInterceptor2"></bean>
    </mvc:interceptor>
</mvc:interceptors>
Copy the code

Each interceptor’s preHandler method returns true

Operation process:

HandlerInterceptor1.. preHandle.. HandlerInterceptor2.. preHandle.. HandlerInterceptor2.. postHandle.. HandlerInterceptor1.. postHandle.. HandlerInterceptor2.. afterCompletion.. HandlerInterceptor1.. afterCompletion..Copy the code

Define two interceptors: HandlerInterceptor1 and HandlerInteptor2

The HandlerInterceptor1 preHandler method returns false, and the HandlerInterceptor2 method returns true.

HandlerInterceptor1.. preHandle..Copy the code

After the first interceptor’s preHandler method returns false, the first interceptor only executes the preHandler method, the other two methods do not execute, all methods of the second interceptor do not execute, and the Controller does not execute.

The HandlerInterceptor1 preHandler method returns true, and the HandlerInterceptor2 method returns false.

HandlerInterceptor1.. preHandle.. HandlerInterceptor2.. preHandle.. HandlerInterceptor1.. afterCompletion..Copy the code

After the second interceptor’s preHandler method returns false, the first interceptor’s postHandler is not executed, and the second interceptor’s postHandler and afterCompletion are not executed. And the controller doesn’t execute.

Conclusion:

PreHandle calls postHandler in the order in which the interceptor is defined. AfterCompletion calls postHandler in reverse order in which the interceptor is defined Called only if preHandle returns trueCopy the code

8.3 Interceptor Application

1. Processing process

1, there is a login page, need to write a controller access page 2, the login page has a submit form action. It needs to be handled in the controller. A) Check whether the user name and password are correct b) Write user information to the session if they are correct C) return successful login or jump to commodity list 3. Interceptor A) Intercept user requests and determine whether the user is logged in b) If the user is logged in. C) If the user does not log in, the login page is displayed.Copy the code

2. User identity authentication

public class LoginInterceptor implements HandlerInterceptor{
    @Override
    Public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // If the login page is displayed, the login page is allowed
        if(request.getRequestURI().indexOf("login.action") > =0) {return true;
        }
        HttpSession session = request.getSession();
        // If the user is already logged in, the system permits the login
        if(session.getAttribute("user")! =null) {return true;
        }
        // The user is not logged in to the login page
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
        return false; }}Copy the code

3. The user logs in to controller

// Login page
@RequestMapping("/login")
public String login(Model model)throws Exception{
    return "login";
}

// Login and submit
//userid: indicates the user account. PWD: indicates the password
@RequestMapping("/loginsubmit")
public String loginsubmit(HttpSession session,String userid,String pwd)throws Exception{
    // Records user identity information to the session
    session.setAttribute("activeUser", userid);
    return "redirect:item/queryItem.action";
}

/ / exit
@RequestMapping("/logout")
public String logout(HttpSession session)throws Exception{
    / / the session has expired
    session.invalidate();
    return "redirect:item/queryItem.action";
}
Copy the code