Until today, every Web application I wrote in Java looked like this:

1– The handler method in @Controller we wrote uses Spring+Hibernate to read data into our custom PO (from hard disk to memory).

2– Then use SpringMVC’s ModelAndView method addObject() to place the resulting PO or List of PO into an instance of ModelAndView.

3– then handler method setViewName(), return. Equivalent to returning string or 4–ModelAndView to SpringMVC, which gives data to the specified JSP page.

The returned data is then read using JSTL tags in the corresponding JSP page and presented to tags in THE HTML for display.

The code for the above procedure is as follows:

First, you write your own Controller code, which is located in the corresponding Web folder

@Controller public class CheckListController extends BaseController{ private CheckListService cls; public CheckListService getCls() { return cls; } @Autowired public void setCls(CheckListService cls) { this.cls = cls; * @return */ @requestMapping ("/checklist") public ModelAndView getCLs(){List< Checklist > lResult = cls.getCLs(); Mav = new ModelAndView(); mav = new ModelAndView(); mav.addObject("lresult", lresult); // Put the return value into the instance of ModelAndView, mav.setViewName(" Checklist /showall"); // Set the JSP page used to display the data return mav; }}Copy the code

The above code is what happens after the Controller part of the Java code in Spring returns, which is done by the SpringMVC ViewResolver, i.e. by the framework, to locate the corresponding JSP page and expose the data to it. Then let’s go to the JSP page

<%@ page language="java" contentType="text/html; Charset = utf-8 "pageEncoding =" utf-8 "% > < % @ taglib uri =" http://java.sun.com/jsp/jstl/core "prefix =" c "% > / / import JSTL <! 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; Charset =ISO-8859-1"> <link rel="stylesheet" href=" CSS /view_all.css"> <title> Display the stylesheet </title> <style> </style> </head> <body> <! <%@ include file=".. / pub/leftMenu. JSP "% > < div id =" testData "> < table border =" 0 px "width =" 100% "> < tr > < th > SN < / th > < th > inspected single < / th > < th > proofer < / th > < / tr >  <c:set var="sn" value="0" /> <! -- Use JSTL to retrieve data returned and exposed in Controller, Then display the data - > < c: forEach var = "cl_temp items" = "${lresult}" varStatus = "vs1" > < c: set var = "sn" value = "${sn + 1}" / > < tr < c: if test="${vs1.index%2==0}" > style="background-color:#eaeaea"</c:if> > <td width = "5%">${sn}</td> <td width = "60%">${cl_temp.clName}</td> <td>${cl_temp.clHandler}</td> </tr> </c:forEach> </table> </div> </body> </html>Copy the code

The above process is fully expressed. I used Spring+SpringMVC to read the database — back to the JSP — and display the data by the JSP.

But it’s too earthy.

There are two reasons:

1– Display pages, that is, pure JSP pages, which is very primitive and a lot of work. We’re going to be using high-end ExtJS so you’re not going to be able to write it that way.

2– This is actually a very rough way to write without understanding SpringMVC.

After reading the code written by Jiang Feng and carefully studying the textbook of SpringMVC, I found that I had to change. Here is the code written by Jiang Feng. Let’s give Mr. Atto a call first.www.jhopesoft.com/You can see his project, source code, and examples running the demo

Quick-build-opensource project adopts ExtJS+Spring+SpringMVC+Hibernate implementation

Let’s look at the most basic scenario: login

As an aside: Actually correct code analysis process should be import the SVN then run, and then see the effect in eclipse control code changes, but I have not successfully imported, so I have to look at the code fragment (using the website demo and download the war file in source code, the actual the linkage, should have but this form can’t linkage analysis code).



The login page is shown in the image above. Let’s look at the code involved in the entire process from displaying the page to entering the username and password and clicking the login button, and then interacting with the database to validate the data.

The page shown above looks like HTML but is actually drawn using ExtJS, which is its own system. After writing the code, you need to compile it using Sencha, and then generate a directory structure similar to the following:



In fact, the directory structure of the final project in Eclipse looks like this



The first page to visit the project is index.html



This is the code for index. HTML, as shown above, and it really doesn’t look anything. But if you’ve learned the basics of ExtJS, you won’t be confused, because ExtJS is a fixed structure. Simply put, app.js is the entry point to everything, so let’s go straight to app.js (you can actually find app.js in the picture of the directory structure above).



The core code imports the app.view.main code, which is a rough statement. According to the basic knowledge of ExtJS, the directory structure is also fixed, and the default is in the APP directory.







This login.js file is the main file in the entire page

Let’s look at the code for the login button:

{ xtype : 'button', name : 'loginButton', scale : 'large', height : 50, iconAlign : 'right', iconCls : 'x-fa fa-sign-in', text: 'n&nbsp; &nbsp; &nbsp; &nbsp; Record & have spent &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Action: 'notice ', action:' onnotice ', notice:Copy the code

The code above is used for the contents of the real red box. The emphasis is on the Click event in the Listeners. Where is this event defined?



The ExtJS specification looks like this, MVVC, as shown below



The Controller section represents the event-related controller for this JS page, which is the file below



So the event is defined in the loginController.js file. Let’s look at the code for the onLoginButton:

OnLoginButton: function(button, e, eOpts){this.validate(false); Function (invalidate){var me = this; var p_form = this.lookupReference('p_form').getForm(); if (! p_form.isValid()) return; var userinfo = p_form.getValues(); userinfo.invalidate = invalidate; userinfo.companyid = cfg.companyid; var url = "login/validate.do"; EU.RS({ url : url, scope : this, params : userinfo, callback : function(result){ var msg = ""; if (result.success) { this.login(userinfo, result.data); Return} switch (result.data) {case "1" : MSG = "please enter the correct verification code!" ; break; Elseif (case "2" : MSG = "MSG") ; break; Elseif (case "3" : MSG = "") ; break; Case "4" : MSG = "username locked" ; break; Elseif (" username ", "MSG") elseif (" username ", "MSG") ; break; Elseif (case "6" : MSG = "MSG") ; break; Case "7" : {eu. showMsg({title: 'message ', message: "User is already online, do you want to force login?" , option : 1, callback : function(rt){ if (rt == 'yes') me.validate(true); }}); break; } default: MSG = "Submit failed, network failure or other unknown reasons!" ; break; } if (! Ext.isEmpty(msg)) EU.toastError(msg); }}); },Copy the code

The code above is the definition of the method in the JS locale, which we call in login.js

Finally, the eu.rs () method is called in the above code, which is defined in another JS file as shown below:



So what does this code do?

Let’s go straight to the extutils.js file, which is the code for the RS() method:

/** * @param {} config */ function(config) {var thiz = this; var params = Ext.isEmpty(config.params) ? {} : config.params; for (var key in params) { var data = params[key]; if (Ext.isArray(data)) params[key] = CU.toString(data); }// convert to the transcoding format accepted by Spring @requestList config.params = cu.toparams (params); // Convert to the spring MVC argument acceptance mode config.async = ext.isempty (config.async)? true : config.async; Asynchronous / / false / / true = = synchronous config. The scope = config. The scope | | thiz; config.dataType = config.dataType || "json"; config.timeout = config.timeout || 30000; config.method = 'POST'; var msg = Ext.isEmpty(config.msg) ? config.async : config.msg; The config. Message = config. Message | | 'are accessing the server, please wait... '; config.target = config.target || Ext.Viewport; var myMask = null; if (msg) { myMask = new Ext.LoadMask({ msg : config.message, target : config.target, removeMask : true }); //,style:'background-color: rgba(208, 208, 208, 0.5); ' myMask.show(); } var caller_callback = config.callback; var caller_errorcallback = config.errorcallback; var datas = null; // // define variable: callback // Variable type: function // variable name: callback // variable value: Var callback = function(type, scope, success, result, response, options) {if (MSG) mymask.hide (); if (success) { datas = result; if (Ext.isFunction(caller_callback)) { Ext.callback(caller_callback, config.scope, [result]); } } else { if (response.status == "999" || response.status == "998") return; if (Ext.isFunction(caller_errorcallback)) { Ext.callback(caller_errorcallback, config.scope, [response, options]); } else {thiz.toasterror (" Failed to access remote server!" ); }} //cfg.crossdomain is defined in app\utils\ config.js, The default value is false if (cfg.crossDomain) {config.url = cfg.requesturl + config.url; config.callback = function(success, result, errortype) { Ext.callback(callback, this, ['jsonp', config.scope, success, result]) } Ext.data.JsonP.request(config); } else {// to config, i.e. LoginController. Callback = function(options, success, response) {var text = responseText; Callback (callback, this, ['json', config.scope, success, cu.toobject (text), options])}; // The core statement ext.ajax. request(config); } return datas; },Copy the code

Var callback = function(type, scope, success, result, response, options) {} The content of a variable is the magic of a function, JS.

Define the callback method first and then call it later in the code.

The following illustration illustrates the standard method ext.callback



The above code has three parts:

1– Complete the config parameter (define a callback method)

2- Determine the crossDomain and redefine the LoginController callback method

3– Execute ExtJS standard method ext.ajax.request ();

The third part is the actual implementation



The standard method is simply to send a request to the URL

The URL is defined in config and has been defined before.

The work of both 1 and 2 is to dynamically define a custom callback method (note that the custom callback is not the standard ExtJS callback)

That’s going to go back to the loginController.js file

The event triggered by the “Login” button in the login. js file is very simple, and the core is to trigger the ExtJS standard ext.ajax.request () method, which sends a request to the URL.

What’s the URL? In case you are blind, LET me paste the code again:

validate : function(invalidate){ var me = this; var p_form = this.lookupReference('p_form').getForm(); if (! p_form.isValid()) return; var userinfo = p_form.getValues(); userinfo.invalidate = invalidate; userinfo.companyid = cfg.companyid; var url = "login/validate.do"; / / this is the URL EU. RS ({URL: the URL, the scope: this,... }Copy the code

Okay, so what happens next?

And then the next thing is irrelevant to ExtJS, because you sent a request. This request will be intercepted by SpringMVC configured in the Tomcat Web project. Hahaha, look familiar?

Depending on the URL, your own hand-written Java file in the Controller section of SpringMVC will come into play.

“login/validate.do”

This url is actually direct, (of course, I also went to the Eclipse project to slowly stare at it) see for yourself:



The url is located by the Controller, the HandlerMapping part of SpringMVC, and the Java file is found and processed, leaving all the work to Spring and SpringMVC.

The code shown above is the code of the Controller in Spring.

/ / omitted the import package as well as other methods com. Jhopesoft. Platform. The controller; @Controller @RequestMapping("/login") public class Login { @Resource private LoginService service; @requestMapping (value = "/validate") @responseBody public ResultBean Validate (HttpServletRequest request, HttpServletResponse response, String companyid, String usercode, String password, Boolean invalidate) { ResultBean result = service.login(companyid, usercode, password, invalidate); if (! result.isSuccess()) return result; UserBean bean = login(request, companyid, usercode); result.setData(bean); return result; // Note the return value type}}Copy the code

The difference between the above code and the Java code of the Controller in Spring written by myself in the past lies in the return value. ModelAndView does not appear in his Java code. According to the code of the directory structure web–service–Dao, the return value type is a custom PO. In the past, we put the PO in the ModelAndView and then jumped to the JSP page to retrieve the data. Now that’s not true, so what does it mean? There are two parts to this: 1) How Spring code gets data from the database; 2– How the returned PO is parsed;

1– The case code gets data from the database:

The Controller directory stores the Java code of SpringMVC, and the Service directory stores the business logic code. The following figure basically reflects all the code of the Java part:



See that the Dao section has only one Java file (one interface and one class)

The Entity folder is filled with PO files generated by eclipse’s integrated Hiberante Tools

Wow that’s Java code. This part was covered in a previous blog post.

2– How is the return value PO resolved

The return value of PO type is actually an instance of PO, which stores data. After it is returned to SpringMVC, SpringMVC parses it into a JSON file, which is returned to the caller of this method in the original login.js file, which returns the method, the callback method. As shown below:



So what does a JSON file look like? A bunch of parentheses, a bunch of colons, a bunch of strings.



Our current concern is how the PO is parsed into json files.

Check out the following blog post:

Blog.csdn.net/fw0124/arti…

Import dependencies through Maven

< the dependency > < groupId > org. Codehaus. Jackson < / groupId > < artifactId > Jackson - core - asl < / artifactId > < version > 1.9.13 < / version >  </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> The < version > 1.9.13 < / version > < / dependency >Copy the code

Then the other two reference documentation is as follows: www.cnblogs.com/fangjian042…

My.oschina.net/lichhao/blo…