preface

This paper mainly explains the development of Controller, and the main knowledge points are as follows:

  • Coding filter
  • Development with annotations
  • annotations@RequestMappingBreak down
  • The business method receives parameters
  • String transfer date
  • Redirection and forwarding
  • Returns a JSON

SpringMVC filter encoder

In the SpringMVC controller, if there is no encoding operation, then the Chinese data is garbled!

Even if we set the encoding using the Request object in the handle() method, it doesn’t work! The reason for this is very simple: we SpringMVC receive the parameters through the parameterless constructor in the controller, and then through the object object of the handle() method to get the specific parameter type.

Struts2 uses an interceptor to automatically solve the Chinese garble problem. Then SpringMVC as a more powerful framework, there must be a corresponding method to help us complete the Chinese garble problem!

Note that the filter encoder can only solve the POST garble problem!

All we need to do is set up the filter encoder in the web.xml configuration file!


    <! -- Encoding filter -->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>
            org.springframework.web.filter.CharacterEncodingFilter
        </filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/ *</url-pattern>
    </filter-mapping>

Copy the code


Annotation development SpringMVC

We use SpringMVC in an XML configuration in the quickstart example, and SpringMVC also supports annotations. [Personally, I like annotation very much.]

When we were in the use of the Action, or inheritance AbstractCommandController class, or display using annotations Controller interface. We don’t have to explicitly inherit or implement any classes when we use annotations!

The development process

Use the @Controller annotation to indicate that this is a SpringMVC Controller!


@Controller
public  class HelloAction  {}Copy the code

Of course, Spring is not aware of such an annotation right now, so we need to configure scan annotations in the configuration file

** Note that: * When configuring the scan path, do not add the suffix.

Otherwise I can’t scan, I don’t know learn Struts2 or other places, the habit of adding.*, so I made a long time!

   <! -- Scan annotations without adding.


    <context:component-scan base-package="zhongfucheng"/>
Copy the code

Write a business method to a controller

@Controller
public class HelloAction {

    / * * * *@RequestMappingIndicates that any request for /hello.action will be processed by this method. Of course. Action can be removed from *@paramModel is similar to ModelAndView in that it encapsulates data into a Request object that we can retrieve@returnReturn to the page where the jump happened *@throws Exception
     */
    @RequestMapping(value="/hello.action")

    public String hello(Model model) throws Exception{
        System.out.println("HelloAction::hello()");
        model.addAttribute("message"."Hello");
        return "/index.jsp"; }}Copy the code

Jump to the INDEX page and get the corresponding value on the home page.


<% @ page contentType="text/html; charset=UTF-8" language="java"% >
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>This is my home page<br>
  ${message}
  </body>
</html>
Copy the code


Of course, annotation-based and XML-based development of SpringMVC is done through mappers, adapters, and view parsers. Only the mapper and adapter are slightly different. But they can be omitted!


    <! Annotation-based mapper (optional) -->
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>

    <! Annotation-based adapter (optional) -->
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>

    <! -- View resolver (optional) -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
Copy the code

Update: the above adapters and mapper are only used before Spring3.1, and are now commonly used after Spring3.1

Mapper: org. Springframework. Web. Servlet. MVC) method. The annotation. The RequestMappingHandlerMapping adapter:  org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapterCopy the code

Of course, these two configurations could also use < MVC: Annotation-driven >> instead of the annotation handler and adapter configurations.


RequestMapping

@requestMapping controls the request path and how it is requested!

A controller writes multiple business methods

So far, we’ve all been writing a business method with a controller, which certainly doesn’t make sense. We have multiple business methods for one Action in Struts2. So what do we do in SpringMVC??

RequestMapping is used to configure which requests correspond to which business methods.


public @interface RequestMapping {
    String[] value() default {};

    RequestMethod[] method() default {};

    String[] params() default {};

    String[] headers() default {};
}

Copy the code

When we request hello.action, the business method we handle is hello()….. When we request bair.action, the business method to handle is bye()


@Controller
public class HelloAction {

    / * * * *@RequestMappingIndicates that any request for /hello.action will be processed by this method. Of course. Action can be removed from *@paramModel is similar to ModelAndView in that it encapsulates data into a Request object that we can retrieve@returnReturn to the page where the jump happened *@throws Exception
     */
    @RequestMapping(value="/hello.action")
    public String hello(Model model) throws Exception{
        System.out.println("HelloAction::hello()");
        model.addAttribute("message"."Hello");
        return "/index.jsp";
    }
    @RequestMapping(value = "/bye.action")
    public String bye(Model model) throws Exception {
        model.addAttribute("message"."Goodbye");
        return "/index.jsp"; }}Copy the code

Modular development

Of course, we often use namespace for module development in Struts2, we can do the same in SpringMVC, and we use @requestmapping again!

As long as the @requestMapping annotation is written to the class, it represents the module.



@Controller
// We know that if it is a comment on the value attribute, we can omit the value
@RequestMapping("/zhongfucheng")
public class HelloAction {

    / * * *@paramModel is similar to ModelAndView in that it encapsulates data into a Request object that we can retrieve@returnReturn to the page where the jump happened *@throws Exception
     * @RequestMappingIndicates that any request for /hello.action will be processed by this method. Of course, action can be removed from the */
    @RequestMapping(value = "/hello.action")
    public String hello(Model model) throws Exception {
        System.out.println("HelloAction::hello()");
        model.addAttribute("message"."Hello");
        return "/index.jsp";
    }

    @RequestMapping(value = "/bye.action")
    public String bye(Model model) throws Exception {
        model.addAttribute("message"."Goodbye");
        return "/index.jsp"; }}Copy the code

So we want the HelloAction controller to handle our request to either: Either http://localhost:8080/zhongfucheng/hello.action, or http://localhost:8080/zhongfucheng/bye.action


Qualify a business control method to allow access only through GET or POST requests

If we want to restrict access to a business control method, only GET or POST requests are allowed. Again, @requestMapping. Just set its Method property!


    @RequestMapping(value = "/bye.action",method = RequestMethod.POST)
    public String bye(Model model) throws Exception {
        model.addAttribute("message"."Goodbye");
        return "/index.jsp";
    }
Copy the code

After I set the request for the business method to POST, I want to access the business method through GET. It won’t work!


The business method writes traditional Web parameters

In addition to writing the Model parameter, our business method can also write request, Response and other traditional Servlet parameters if necessary. This is also available at….

However, we don’t recommend using traditional Web parameters because of the coupling


@RequestMapping(method=RequestMethod.POST,value="/register")
	public String registerMethod(HttpServletRequest request,HttpServletResponse response) throws Exception{
		
		// Get the username and salary
		String username = request.getParameter("username");
		String salary = request.getParameter("salary");
		System.out.println("User registration -->" + username + ":" + salary);
		
		// Bind to the session domain object
		request.getSession().setAttribute("username",username);
		request.getSession().setAttribute("salary",salary);
		
		// Redirect/JSP /success.jsp page
		//response.sendRedirect(request.getContextPath()+"/jsp/success.jsp");
		
		// Forward/JSP /ok.jsp page
		request.getRequestDispatcher("/jsp/ok.jsp").forward(request,response);
		
		// forward (advocate)
		return "/jsp/success.jsp";
	}
Copy the code

Minor detail: If we return a true path and we use forward or redirect in our program… Then the specific jump position is according to our procedure jump path prevail!

The business method collects parameters

The name of the member variable is the same as the name of the member variable brought in from the web side. And, given the set method for the member variable, Struts2’s interceptor will automatically assign the parameters brought from the Web to our member variable….

So how do you collect parameters in SpringMVC ???? We can’t define member variables like Struts2 because SpringMVC is singleton and Struts2 is multi-instance. So here’s what SpringMVC does:

  • The business method writes parameters
  • The parameter name must be the same as the data name brought from the Web end

Receive common parameters

If it is a common parameter, we directly write on the method with the same name as the web side brought over the parameter!


<form action="${pageContext.request.contextPath}/hello.action" method="post">
    <table align="center">
        <tr>
            <td>User name:</td>
            <td><input type="text" name="username"></td>
        </tr>
        <tr>
            <td>Serial number</td>
            <td><input type="text" name="id"></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="Submit">
            </td>
        </tr>
    </table>

</form>

Copy the code

    @RequestMapping(value = "/hello.action")
    public String hello(Model model, String username, int id) throws Exception {

        System.out.println("Username is:" + username);
        System.out.println("The number is:" + id);

        model.addAttribute("message"."Hello");
        return "/index.jsp";
    }

Copy the code

Effect:


Receive a JavaBean

We process the parameters of the form, and if the form brings in a lot of data, we wrap it in Javabeans. So we can do the same thing in SpringMVC.

  • Create a Javabean
  • The javaBean property is the same as the name that comes with the form
  • Write the name of the Javabean on the business method

Create a JavaBean with the same properties as the name brought in from the form


public class User {

    private String id;
    private String username;

    public User(a) {}public User(String id, String username) {
        this.id = id;
        this.username = username;
    }
    public String getId(a) {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername(a) {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString(a) {
        return "User{" +
                "id='" + id + '\' ' +
                ", username='" + username + '\' ' +
                '} '; }}Copy the code

Write a Javabean to the business method parameters


    @RequestMapping(value = "/hello.action")
    public String hello(Model model,User user) throws Exception {

        System.out.println(user);
        model.addAttribute("message"."Hello");
        return "/index.jsp";
    }

Copy the code


Collect array

Collecting arrays is similar to collecting ordinary parameters, as shown in the following code.


<form action="${pageContext.request.contextPath}/hello.action" method="post">
    <table align="center">
        <tr>
            <td>User name:</td>
            <td><input type="text" name="username"></td>
        </tr>
        <tr>
            <td>hobby</td>
            <td><input type="checkbox" name="hobby" value="1">basketball</td>
            <td><input type="checkbox" name="hobby" value="2">football</td>
            <td><input type="checkbox" name="hobby" value="3">volleyball</td>
            <td><input type="checkbox" name="hobby" value="4">badminton</td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="Submit">
            </td>
        </tr>
    </table>

</form>
Copy the code

The business method gets the parameters


    @RequestMapping(value = "/hello.action")
    public String hello(Model model,int[] hobby) throws Exception {


        for (int i : hobby) {
            System.out.println("Who likes sports is:" + i);

        }

        model.addAttribute("message"."Hello");
        return "/index.jsp";
    }

Copy the code

Effect:

collectList<JavaBean>A collection of

We can’t accept arguments like List in Spring’s business methods. SpringMVC gives us an alternative!

We use a JavaBean to encapsulate the collection and give the corresponding set and GET methods. So when we receive parameters, we receive Javabeans


/** * encapsulates multiple Emp objects *@author AdminTC
 */
public class Bean {
	private List<Emp> empList = new ArrayList<Emp>();
	public Bean(a){}
	public List<Emp> getEmpList(a) {
		return empList;
	}
	public void setEmpList(List<Emp> empList) {
		this.empList = empList; }}Copy the code

Business methods receive JavaBean objects


	/** * Add employees */
	@RequestMapping(value="/addAll",method=RequestMethod.POST)
	public String addAll(Model model,Bean bean) throws Exception{
		for(Emp emp:bean.getEmpList()){
			System.out.println(emp.getUsername()+":"+emp.getSalary());
		}
		model.addAttribute("message"."Successful batch increase of employees.");
		return "/jsp/ok.jsp";
	}
Copy the code

Write empList directly on the JSP page [table below].


<form action="${pageContext.request.contextPath}/emp/addAll.action" method="POST">
    	<table border="2" align="center">
    		<caption><h2>Batch registered employees</h2></caption>
    		<tr>
    			<td><input type="text" name="empList[0].username" value="Ha ha"/></td>
    			<td><input type="text" name="empList[0].salary" value="7000"/></td>
    		</tr>
    		<tr>
    			<td><input type="text" name="empList[1].username" value="Ha ha"/></td>
    			<td><input type="text" name="empList[1].salary" value="7500"/></td>
    		</tr>
    		<tr>
    			<td><input type="text" name="empList[2].username" value="Monitor"/></td>
    			<td><input type="text" name="empList[2].salary" value="8000"/></td>
    		</tr>
    		<tr>
    			<td><input type="text" name="empList[3].username" value="Ketch"/></td>
    			<td><input type="text" name="empList[3].salary" value="8000"/></td>
    		</tr>
    		<tr>
    			<td><input type="text" name="empList[4].username" value="Green Students"/></td>
    			<td><input type="text" name="empList[4].salary" value="9000"/></td>
    		</tr>
    		<tr>
    			<td colspan="2" align="center">
    				<input type="submit" value="Bulk registration"/>
    			</td>
    		</tr>
    	</table>
    </form>
Copy the code

This approach doesn’t seem that hard to understand, we’re just wrapping up a layer [similar to receiving normal Javabeans].


Collect multiple models

It is possible to have both User model data to collect and Emp model data to collect…. on JSP pages And the attributes of the User model are the same as those of the Emp model…. What should we do now??

We can also abstract up a Bean with Emp and User objects on top of the User and Emp models

/** * encapsulates the User and Admin object *@author AdminTC
 */
public class Bean {
	private User user;
	private Admin admin;
	public Bean(a){}
	public User getUser(a) {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
	public Admin getAdmin(a) {
		return admin;
	}
	public void setAdmin(Admin admin) {
		this.admin = admin; }}Copy the code

When JSP pages are collected, just give the corresponding type.


	<form action="${pageContext.request.contextPath}/person/register.action" method="POST">
		<table border="2" align="center">
			<tr>
				<th>The name</th>
				<td><input type="text" name="user.username" value="${user.username}"/></td>
			</tr>
			<tr>
				<th>Monthly salary</th>
				<td><input type="text" name="user.salary" value="${user.salary}"></td>
			</tr>
			<tr>
				<th>In the time</th>
				<td><input 
						type="text" 
						name="user.hiredate" 
						value='<fmt:formatDate value="${user.hiredate}" type="date" dateStyle="default"/>'/></td>
			</tr>
			<tr>
				<td colspan="2" align="center">
					<input type="submit" value="General User Registration" style="width:111px"/>
				</td>
			</tr>
		</table>	
	</form>	
Copy the code

String to date type

In Struts2, the date is automatically parsed by default if the string type sent to the Web is YYYY-MM-DD hh: mm :ss. The date is automatically parsed by default if the string type is other than YYYY. Either use a custom converter to parse, or use your own Java program to parse….

In SpringMVC, even the type YYYY-MM-DD HH :MM: SS is not automatically resolved. Let’s look at the following example:

The JSP passes a string about the date format to the controller…

<form action="${pageContext.request.contextPath}/hello.action" method="post">
    <table align="center">
        <tr>
            <td>User name:</td>
            <td><input type="text" name="username"></td>
        </tr>
        <tr>
            <td>Date of birth</td>
            <td><input type="text" name="date" value="1996-05-24"></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="Submit">
            </td>
        </tr>
    </table>

</form>

Copy the code

The User object defines the Date member variable to receive


 public Date getDate(a) {
        return date;
    }
    public void setDate(Date date) {
        this.date = date;
    }
Copy the code

The business method gets the Date value


    @RequestMapping(value = "/hello.action")
    public String hello(Model model, User user) throws Exception {

        System.out.println(user.getUsername() + "Date of birth is:" + user.getDate());


        model.addAttribute("message"."Hello");
        return "/index.jsp";
    }
Copy the code

SpringMVC does not support this type of argument:


Now the problem is thrown out, how do we solve it ????

For SpringMVC are similar to the struts 2 type converter so we use a method: if we use the inheritance AbstractCommandController class to develop, we can rewrite initBinder () method.

The concrete implementation looks like this:


    @Override
    protected void initBinder(HttpServletRequest request,ServletRequestDataBinder binder) throws Exception {
        binder.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));
    }

Copy the code

So now we are using annotations for development, there is no override method. So all we need is a comment that says I want to override this method!


    @InitBinder
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
        binder.registerCustomEditor(
                Date.class,
                new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
        
    }
Copy the code

Visit again:

Note that if we use Oracle insert time, then we need to write TimeStrap timestamp in SQL statement, otherwise it will not work!


Results are redirected and forwarded

When we do development, we often edit the data and then go back to the display list. We use configuration files for redirection or forwarding in Struts2:

Our SpringMVC is very simple, just write the keyword before jump!



    public String hello(Model model, User user) throws Exception {

        System.out.println(user.getUsername() + "Date of birth is:" + user.getDate());
        model.addAttribute("message", user.getDate());
        return "redirect:/index.jsp";
    }
Copy the code

Similarly, if you want to request again, then we just write the corresponding request path!


    @RequestMapping(value = "/hello.action")
    public String hello(Model model, User user) throws Exception {

        return "redirect:/bye.action";
    }

    @RequestMapping("/bye.action")
    public String bye(a) throws Exception {

        System.out.println("I'm coming in bye method");
        return "/index.jsp";
    }
Copy the code


Return JSON text

Let’s review how Struts2 returns JSON text:

  • Import the jar package
  • The object to return JSON text gives the get method
  • Inherit the JSON-default package in the configuration file
  • The return value type of the result tag is JSON

So what do we do in SpringMVC?

Import two JSON development packages

  • Jackson – core – asl – 1.9.11. Jar
  • Jackson – mapper – asl – 1.9.11. Jar

Comment on the business method that returns JSON:


    @RequestMapping(value = "/hello.action")
    public
    @ResponseBody
    User hello(a) throws Exception {

        User user = new User("1"."zhongfucheng");
        return user;
    }
Copy the code

Configuring the JSON Adapter


	
		<! Jar (1) import jackson-core-asl-1.9.9.jar and jackson-mapper-asl-1.9.9.jar (2) use the @responseBody annotation between the business method return value and permission to indicate that the return value object needs to be converted to JSON text 3) Write the following code in the spring. XML configuration file:
			<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
				<property name="messageConverters">
						<list>
							<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
						</list>
				</property>
		    </bean>
	
Copy the code

Test the JSP


	<input type="button" value="Emp turn JSON"/><p>

    <input type="button" value="The List < Emp > turn JSON." "/><p>

    <input type="button" value="The Map < String, Object > turn JSON." "/><p>

    <! -- Map<String,Object>
    <script type="text/javascript">
        $(":button:first").click(function(){
            var url = "${pageContext.request.contextPath}/hello.action";
            var sendData = null;
            $.post(url,sendData,function(backData,textStaut,ajax){
                alert(ajax.responseText);
            });
        });
    </script>

Copy the code

Testing:

The Map test:


    @RequestMapping(value = "/hello.action")
    public
    @ResponseBody
    Map hello(a) throws Exception {

        Map map = new HashMap();

        User user = new User("1"."zhongfucheng");
        User user2 = new User("12"."zhongfucheng2");
        map.put("total", user);
        map.put("rows", user2);


        return map;
    }
Copy the code

Update — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — –

If the data passed in is in JSON format, we need to use another annotation @requestBody to convert the requested JSON data into a Java object


conclusion

  • Development using annotations avoids inheriting redundant classes and is very concise and efficient.
  • It is not enough to just set the encoding format of the request in order to keep Chinese garbled. Because SpringMVC encapsulates data through a parameterless constructor. We can use the filter provided by SpringMVC to solve the Chinese garble problem.
  • RequestMapping sets our specific access paths and can be developed in modules. For these two reasons, we can write multiple business methods in an Action.
  • RequestMapping can also restrict whether the request method is GET or POST.
  • In our business method, we can also use traditional objects like Request and Response, but it’s best not to use them if you don’t have to.
  • For SpringMVC itself to wrap the parameters for us, we need to use the same names that request brought in. If they are different, we need to use annotations to help us resolve them.
  • If you need to encapsulate a collection, or encapsulate a number of beans, then our backend Javabeans need to encapsulate one more layer, write beans on the business method. Of course, you specify the properties of the corresponding Bean properties on the Web page.
  • The string-to-date object uses the @initBinder annotation to override methods.
  • To return a JSON object, we need the @responseBody annotation, and to receive JSON data wrapped in javabeans, we need the @requestBody annotation. Then create the corresponding bean on the configuration file.

If the article has the wrong place welcome to correct, everybody exchanges with each other. Students who are used to reading technical articles on wechat and want to get more Java resources can follow the wechat public account :Java3y