A open source implementation of Struts, MVC

xiaoxiao2021-03-06  41

Struts, MVC is an open source implementation Author: Malcolm G. Davis from: IBM This article describes Struts, it is using a servlet and JavaServer Pages technologies Model-View-Controller implementation. Struts helps you control changes in the web project and improve the level of specialization. Although you may never use Struts to implement a system, you can use some of these ideas for your future servlet and JSP webpage implementation. Introduction Primary school students can also post HTML web pages on the Internet. However, primary school students' web pages and professional development websites have quality. Web designers (or HTML developers) must understand colors, users, production processes, webline layouts, browser compatibility, image creation, and JavaScript, and more. The beautiful website needs to do a lot of work, most Java developers pay more attention to create a beautiful object interface, not the user interface. JavaServer Pages (JSP) technology provides web designers and Java developers with a link. If you have developed a large web application, you understand the meaning of changing the word. "Model - View - Controller" (MVC) is a design pattern used to help you control changes. The MVC weakens the coupling between the business logic interface and the data interface. Struts is an MVC implementation that uses Servlet 2.2 and JSP 1.1 tags (belonging to J2EE specification) as part of the implementation. Although you may never use Struts to implement a system, you know that Struts may allow you to use some of the ideas for the JSP implementation of your later servlet. In this article, I will discuss the advantages and disadvantages of the web page with a JSP file, which may be what you are familiar. Then I will discuss strut and explain how it controls changes in your web project and improves the level of specialization. Finally, I will re-develop this simple JSP file, I have taken into account in web designers and changes during the development process. A JSP file is a Java Servlet JavaServer Page (JSP) file is just another way of reviewing the servlet. The concept of JSP file allows us to view Java servlet as an HTML page. JSP eliminates the annoying PRINT () statement that often appears in the Java code. The JSP file is first preprocessed as .java files, then compile to .class files. If you are using Tomcat, you can view the pre-processed .java files in the Work directory. Other containers may store .java and .class files in other locations; this location is related to the container. Figure 1 illustrates the process from the JSP file to the servlet. Figure 1. Process from JSP files (this is clearly different from Microsoft Active Server Page (ASP). TheASP is compiled into memory, not compiled into a separate file.) Simple independent JSP file in small JSP In applications, data, business logic, and user interfaces are often seen in a code module. In addition, applications typically include logic used to control application flow. Listing 1 and Figure 2 show a simple JSP file that allows users to join a mailing list.

Listing 1. Join.jsp - a simple request and response JSP file <% @ page language = "java"%> <% @ page import = "business.util.validation"%> <% @ page import = "Business .db.mailingList "%> <% string error ="; string email = request.getParameter ("email"); // Is there an email address if (email! = null) {// verification input ... if Business.util.validation.isvalidemail (email)) {// Storage Enter ... try {business.db.mailinglist.addemail (email);} catch (exception e) {error = "Error adding email address to system. " E; Error.Length () == 0) {%> // Redirect to Welcome Page ... <%}} else {// Set the error message and resculate the web error = email "is not a value {email =";}}}}}}}}}}}}}}}}}}}}}}}}}}}%> join mailing list < / title> </ head> <body> <font color = red> <% = error%> </ font> <br> <h3> Enter Your email to join the group </ h3> <form action = "join. JSP "Name =" joinform "> <input name =" email "id =" email "value = <% = email% >> </ INP UT> <input type = Submit value = "submit"> </ form> </ body> </ html> Figure 2. In a simple request and response, the JSP file sets the data, controls the process of the next web page and creates HTML This mailing list JSP file is an independent, autonomous module that completes all tasks. Only code not included in this JSP file is the actual verification code included in IsValideMail () and the code to store the email address into the database. (ISVALIDEMAIL () method seems to be of course selection in reusable code, but I have seen the isvalidemail () code directly embedded in the web page. The advantages of a single page method are easy to understand, and it is also easy to build. In addition For a variety of graphical development tools, it is easy to get started.</p> <p>Join.JSP activity 1. Display the open input page. 2. Read the value of Email from the form parameter. 3. Verify the Email address. 4. If the email address is valid: ☆ Add this address to the database. ☆ Redirect to the next page. 5. If the email address is invalid: ☆ Set an error message. ☆ Re-display Join.jsp containing the error message. The consequences of single-page methods ☆ HTML and Java strong coupling in JSP files must be both web designers, and Java developers. The result is usually either a very bad Java code, either a grunge web page, sometimes even Java code and web pages are very bad. ☆ The shortcomings of Java and JavaScript have gradually achieved some JavaScript with the page with the web page. This script may be confused with Java code when JavaScript appears in a web page. An example of possible confusion is to verify the Email domain using JavaScript using the client. ☆ The embedded process logic understands the entire process of the application, and you must browse all the web pages. Imagine the intricate logic of the website with 100 webpages. ☆ In addition to a bad look, HTML tag, Java code, and JavaScript code are concentrated in a web page and make debugging quite difficult. ☆ Strengthening business logic or data may involve each page of the associated. ☆ Aesthetics is in a large web page, this code style looks messy. When I was developed by Microsoft ASP, I often saw a 1000-line web page. Even with color syntax shows that reading and understanding these codes is still more difficult. Please don't join too much Java code in my HTML in Listing 1, not having a lot of HTML in the Java code, but there is a lot of Java code in the HTML file. From this point of view, in addition to allowing web designers to write Java code, I don't actually do anything. However, we are not all; in JSP 1.1, we get a new feature called "tag". The JSP tag is just a way to extract the code from the JSP file. Some people regard JSP tags as a macro of the JSP file, which is included in the servlet used for this tag. (Macro's view is largely correct.) For the same reason, I don't want to see HTML tags in the Java code, and I don't want to see Java code in the JSP file. The entire starting point of JSP technology is to allow web designers to create servlets without entanglement of Java code. The tag allows Java programmers to extend JAVA code into HTML to extend JSP files. Figure 3 shows the general concepts of extracting code from the JSP page and put them in a JSP tag. Figure 3. JSP Mark Listing 2 is an example used to illustrate the functionality of the Struts tag. In Listing 2, the normal HTML <form> tag is replaced with a struts <form: form> tag. Listing 3 shows the results of the browser received HTML. The browser gets HTML <form> tags, but with additional code, such as JavaScript. Additional JavaScript activates the Email address domain. The <form: form> tag code for the server is created, and the web design personnel will no longer contact JavaScript.</p> <p>Listing 2. Struts FORM flag <form: form action = "join.do" FOCUS = "email"> <form: text property = "email" size = "30" maxlength = "30" /> <form: Submit Property = "Submit" value = "submit" /> </ form: form> Listing 3. Send to the browser results HTML <form name = "joinform" method = "post" action = "join.do; jsessionid = ndj71hjo01" > <Input type = "text" name = "email" maxlength = "30" size = "30" value = "> <input type =" submit "name =" submit "value =" submit "> </ form> <script language = "javascript"> <! - document.joinform.email.focus () // -> </ script> Notes about JSP tags: ☆ JSP tag requires a run JSP 1.1 or higher container. ☆ JSP tag is running on the server without explaining the client as the HTML tag. ☆ JSP tag provides an appropriate code reuse mechanism. ☆ You can add HTML and JavaScript to your web page using a JSP mechanism called include. However, developers often create huge JavaScript library files, which are included in the JSP file. As a result, the HTML page that is returned to the client is much larger than the required HMTL page. The correct usage of include only HTML code segments that generate it such as header and footer. ☆ The JSP tag makes the development role more specialized by extracting Java code. Model - View - Controller (MVC) JSP tag only solves some problems. We have to handle issues such as verification, process control, and update applications. This is where the MVC works. MVC helps solve some of the problems encountered by the single module method by dividing the problem: ☆ Model model contains the core functions of the application. The model encapsulates the status of the application. Sometimes the only function it contains is status. It doesn't know anything about the view or controller. ☆ View view of the view provides a model. It is the appearance of the application. The view can access the model's read method, but the write method cannot be accessed. In addition, it doesn't know anything about the controller. The view should be notified when changing the model. ☆ Controller The controller responds to the user's input. It creates and sets the model. MVC Model 2 Web proposes some unique challenges to software developers, the most obvious is the stateless connection of clients and servers. This stateless behavior makes the model difficult to change the notification view. On the Web, in order to find changes to the application status, the browser must re-query the server. Another major change is different from the techniques used by the view and implementation models or controllers.</p> <p>Of course, we can generate HTML using Java (or Perl, C / C or other languages). There are several shortcomings in this approach: ☆ Java programmers should develop services instead of HTML. ☆ You need to change the code when changing the layout. ☆ Service users should be able to create a web page to meet their specific needs. ☆ Web designers cannot participate directly in web development. ☆ HTML in the ejection code is difficult. For the web, you need to modify the standard MVC form. Figure 4 shows the MVC's web rewrite, usually also known as MVC Model 2 or MVC 2. Figure 4. A implementation Struts of MVC Model 2 Struts, MVC 2 is a set of collaborative classes, servlets, and JSP tags that make up a reusable MVC 2 design. This definition indicates that struts is a frame, not a library, but Struts also contains a wealth of tag libraries and utility classes independent of the framework. Figure 5 shows an overview of Struts. Figure 5. Struts Overview Struts Overview ☆ Client Browser Creates an event from each HTTP request from the client browser. The Web container will respond with an HTTP response. ☆ Controller The controller receives a request from the browser and decides where to send this request. For Struts, the controller is a command design pattern implemented by a servlet. Struts-config.xml file configuration controller. ☆ Business logic logic update the status of the model and help control the process of the application. For Struts, this is done by the Action class "thin" packaging as the actual business logic. ☆ The status model of the model represents the status of the application. Business object updates the status of the application. The ActionForm bean represents the status of the model in the session stage or the request grade, not in the persistence. JSP files read information from Actionform Bean using JSP tags. ☆ View view is a JSP file. There is no process logic, no business logic, and there is no model information - only the tag. The tag is one of the factors that make Struts different from other frameworks (such as Velocity). Detailed analysis of Struts Figure 6 shows a simple UML diagram of the org.apache.struts.Action package. Figure 6 shows the simplest relationship between ActionServlet, ACTIONFORM (Form State), and Action (Model Wrapper). Figure 6. UML diagram ActionServlet class Do you still remember the day of the function map with the relationship between Command (Action & ActionForm)? At that time, you will map some input events to a function pointer. If you are familiar with this, you will put the configuration information in a file and load this file at runtime. The function pointer array once is a well-programmed way to use C language. Now much now, we have Java technology, XML, J2EE, and more. The Struts controller is a servlet that maps events (events typically http post) to classes. As you expected - the controller uses the configuration file to make you don't have to hardcode these values. The time changed, but the method is still. ActionServlet is the COMMAND section implemented by the MVC, which is the core of this framework.</p> <p>ActionServlet (Command) creates and uses Action, ActionForm, and ActionForward. As mentioned earlier, the struts-config.xml file configures the Command. When you create a web project, you will extend Action and ActionForm to resolve specific issues. File Struts-Config.xml Indicates how the ActionServlet uses these extensions. This approach has several advantages: ☆ The entire logic process of the application is stored in a hierarchical text file. This makes it easier to view and understand it, especially for large applications. ☆ Web designers don't have to pay portions to understand the process of the application. ☆ Java developers don't have to recompile the code after the change process. You can add a Command feature by extending an ActionServlet. Actionform class ActionForm maintains the session status of the web application. ActionForm is an abstract class that must create subclasses of this class for each input form model. When I said the input form model, it means that Actionform represents the general sense of the HTML form setting or update. For example, you may have a useerActionform set by the HTML form. The Struts framework will do the following: ☆ Check if the useerActionform exists; if there is no existence, it will create an instance of the class. ☆ Struts will set the status of the useerActionform using the corresponding domain in HTTPSERVLETREQUEST. There is not much annoying request.getParameter () call. For example, the STRUTS framework extracts FNAME from the request stream and calls useerActionform.setFName (). ☆ The Struts Frame will update its status before passing the useerActionform before using UserAction. ☆ Before passing it to the Action class, Struts also calls the validation () method for the userActionform for form status verification. Note: This is not always wise. Other web or services may use UseractionForm, in these places, verification may vary. Perform status verification in the UserAction class may be better. ☆ UserActionForm can be maintained in the session level. Note: ☆ Struts-config.xml file controls the mapping relationship between the HTML form request and the ActionForm. ☆ Multiple requests can be mapped to UseractionForm. ☆ The UseractionForm can map across multiple pages to perform operations such as the wizard. The Action class Action class is a packaging of business logic. The use of the Action class is to convert HTTPSERVLETREQUEST to business logic. To use Action, create its subclass and override the process () method. ActionServlet (Command) passes the parameterized class to ActionForm using the Perform () method. There is still not much annoying request.getParameter () call. When the event progresses to this step, the input form data (or HTML form data) has been extracted from the request stream and transferred to the actionform class. Note: Please pay attention to simplicity when expanding the Action class. The Action class should control the process of the application without controlling the logic of the application. We can provide greater flexibility and reusability by placing business logic in separate packages or EJBs. Another way to consider the Action class is Adapter design mode. The use of Action is to "convert the interface interface to another interface required to the client.</p> <p>Adapter enables classes to work together. If there is no Adapter, these classes cannot work together because of incompatible interfaces. (Excerble Oo Software) (Excerne Oo Software). The client in this example is an ActionServlet, which does not know about our specific business class. Therefore, Struts provides a business it understands. Interface, ie, by extending action, we keep our business interface to keep compatible with the Struts service interface. (A interesting discovery is that the action is a class rather than the interface) .Action starts to be an interface, but it turns into a class It is a gold income.) Error class UML map (Figure 6) also includes ActionError and ActionerRors.ActionError encapsulated a single error message. TheActionerRRORS is a container of the ActionError class. View can use tags to access these classes. Acuts Write list Mode. Figure 7. UML diagram ActionMApping class input event between Command (ActionServlet) and Model (Action) is usually occurring in the HTTP request form, the servlet container converts HTTP request to httpservletRequest. Controller View Entering Event Associate a request to an action class. Struts-config.xml determine which Action class call. Struts-config.xml configuration information is converted to a set of actionMApping, while the latter is placed in the ActionMappings container. (You may have not yet Notice this, the class ends with S is the container) ActionMApping contains information about how a specific event is mapped to a specific action .ActionServlet (Command) passes an actionMApping to the Action class via the Perform () method. This allows action to access Control flow information. ActionMAppings actionMappings is a collection of ActionMapping objects. Retracence List Sample Let's take a look at how the Struts solves these problems that troubles join.jsp. The rewritable solution consists of two projects. The first one The project contains the logical part of the application, and this application is alone. Establish a web application. This independent layer may be a public service layer implemented by EJB technology. For convenience of explanation, I created a package called Business on the ANT build process. There are several reasons to promote our use of independent business layers: ☆ Divided responsibility individual envelopers can delegate responsibility within the development team. This also helps to improve the responsibility of developers. ☆ Universal We envisage developers as a business software. Place it in another package make it more like a universal. This package may be universal, or it may be developed by another group inside the organization. ☆ Avoid unnecessary buildings and unit tests. Separate build processes help to avoid unnecessary buildings and unit tests. ☆ Use interface development to develop and avoid unnecessary coupling, it helps to think about problems from the views of the interface. This is an extremely important aspect. When developing your own business pack, these business classes should not be concerned that the web application performs calls, or the stand-alone application executes calls. Therefore, you should avoid any references to the Servlet API or Struts API call in the business logic layer. ☆ Stability is not per tissue every day, every week or even monthly overhaul. Therefore, the stable interface point is important when developing.</p> <p>It is impossible to think that the web project should also be in the change phase because the business package is in a change phase. Business Building Note I use the Ant build project and run unit test with JUnit. Business.zip contains everything you need to build a business project, except for Ant and Junit. This package will build a class, run unit test, create a Java document, and JAR file, and finalize all of these content to a zip file to send to customers. As long as you make some modifications to build.xml, you can deploy it to other platforms. Business.jar is located in the Web Download section, so you don't have to download and build this business package. The second project of the Web project is a web application developed with Struts. You will need a container that meets JSP 1.1 and Servlet 2.2 specification. The fastest introductory method is to download and install Tomcat 3.2. Before there is a Struts 1.0 release, I suggest you get the latest version from the Jakarta project. This is a big problem for me. I can't make sure that my web project sample can work with Struts you downloaded. Struts is still changing, so I have to update my project frequently. In this project, I am using jakarta-struts-20010105.zip. Figure 8 shows the structure of this web project. If you have installed Ant, run this version will create a WAR file called JoinStruts.war, you can always deploy this file. Figure 8. Structure Listing 4 of the Web Project 4 shows the conversion JSP file called Joinmvc.jsp. This file is from the original 50 line to 19 lines and now does not contain any Java code. From the perspective of web designers, this is a huge improvement.</p> <p>Listing 4. Joinmvc.jsp - Revitalize simple JSP <% @ page language = "java"%> <% @ taglib URI = "/ web-inf / struts.tld" prefix = "struts"%> <% @ Taglib URI = "/ Web-INF / STRUTS-FORM.TLD" prefix = "form"%> <html> <head> <title> <struts: message key = "join.title" /> </ title> </ Head> <body bgcolor = "white"> <form: errors /> <h3> Enter Your email to join the group </ h3> <form: form action = "join.do" FOCUS = "email"> <form: TEXT Property = "Email" size = "30" maxlength = "30" /> <form: submit property = "submit" value = "submit" /> </ form: form> </ body> </ html> webpage Change The following is a list of changes that have changed after using the Struts tag library: ☆ import <% @ Taglib URI = "/ Web-inf / struts.tld" prefix = "struts"%> Used for Java code <% @ Page Import? Has been replaced with <% @ taglib Uri for the Struts tag library. ☆ Text <struts: message key = "join.title" /> The resource property file contains the text of Join.Title. In this case, the ApplicationResources property file contains this name value. This makes the string easier to view and internationalize. ☆ Error <form: errors /> an ActionServlet or ActionForm Buy an error message to display. These error messages can also be included in the properties file. ApplicationResources also provides a method of formatting errors to set ERROR.Header and Error.Footer. ☆ HTML form <form: form action = "join.do" FOCUS = "email"> □ JSP <form> tag and attribute replaces HTML <form> tag and attribute. <form action = "join.jsp" name = "join"> has been changed to <form: form action = "join.do" focus = "email">. □ HTML <Input> Tags have been replaced with <form: text />. □ HTML <Submit> Tags have been replaced with <form: submit />.</p> <p>Model - Session Status Joinform extends ActionForm and contains form data. The form data in this example only has an email address. I have added a write method and reading method to the email address for framework access. For convenience of explanation, I rewrite the validate () method and use the Struts tracking function. Struts will create Joinform and set status information. Model - Business Logic As mentioned earlier, Action is an interface between the controller and the actual business object. JoinAction wrapped in call to Business.jar, which was originally in the join.jsp file. JoinAction's Perform () method lists in Listing 5. Listing 5. - JoinAction.perform () public ActionForward perform (ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {// we will extract the properties and parameters used JoinForm joinForm = (JoinForm) form; String email = joinform.getemail (); actionerrors errors = new actionerrors (); // Storage input .... try {business.db.mailinglist.addemail (email);} catch (exception e) {// record log, Print stack // Disconnect the error to the user errors.add ("Error.mailing.db.add");} // Save the specified error message button to the specified error message button to // HTTP request for use in <struts: errors> tag. if (! ErrorS.empty ()) {SaveErRors (Request, Errors); // Returns to the initial form return (maping.getinput ());} // Transfer control to action.xml 'Success' URI RETURN ("Success"));} Note: Perform () Returns a class called ActionForward that does this class notify the controller Next to do what operations do. In this example, I use the mapping that is incorporated from the controller to determine the next step. The controller I have modified the JSP file and create two new classes: A class is used to include form data, a class to call the business package. Finally, I integrate them by modifying profile struts-config.xml. Listing 6 shows the Action elements I added, this element is used to control the process of JoinMvc.jsp.</p> <p>Listing 6. Action configuration <action path = "/ join" name = "joinform" type = "web.mailinglist.joinaction" scope = "request" infut = "/ joinmvc.jsp" Validate = "true"> <forward name = "SUCCESS" path = "/ welcome.html" /> </ action> Action element describes mapping from the request path to the corresponding Action class, should use these classes to handle requests from this path. Each request type should have a corresponding action element to describe how to handle the request. For JOIN requests: 1. Joinform is used to accommodate form data. 2. Because Validate is marked as true, Joinform will try to perform self-authentication. 3. Web.mailingList.joinAction is an Action class used to process the request to this map. 4. If everything goes well, the request will go to Welcome.jsp. 5. If there is a business logic failure, the process will return to Joinmvc.jsp, which is the first page that was originally issued. Why is this so? In the Action Element of Listing 6, there is an attribute called INPUT whose value is "/jinmvc.jsp". In my joinaction.perform () (as shown in Listing 5), if the business logic fails, Perform () returns an actionforward and as mapping.getInput () as a parameter. The getInput () in this example is "/joinmvc.jsp". If the business logic fails, it will return to Joinmvc.jsp, which is the first page that was originally issued. The comparison before and after using Struts is as seen in Figure 9, has a significant increase in complexity and layers. No longer there is a direct call from the JSP file to the Service layer. Figure 9. Advantages of comparing Struts before and after Struts ☆ The use tag feature of the JSP tag mechanism is obtained from the JSP file and the abstract Java code. This feature is well integrated into JSP-based development tools, which allows you to write code with tags. ☆ Why is the tag library to invent a wheel, or a tag library? If you can't find the tag you want in the library, then you will define it. Also, if you are learning JSP tag technology, Struts provides you with a starting point. ☆ Open source You can get all the advantages of open source, such as viewing code and let everyone using the library check the code. Many people can check very well. ☆ MVC implementation example If you want to create your own MVC implementation, Struts can increase your knowledge. ☆ Management problem spatial grasping is a great way to solve problems and make problems can manage. Of course, this is a double-edged sword. The problem is getting more complicated, and more and more management is needed. Struts Disadvantages ☆ Still in the initial Struts development is still in the primary stage. They are working hard to the release version 1.0, but as with any 1.0 versions, it is impossible to do it. ☆ This frame is still changing in rapid changes. Struts 1.0 varies greatly compared to Struts 0.5.</p> <p>In order to avoid the use of the method that does not agree, you may need to download the latest Struts over one day. In the past 6 months, I witnessed the Struts library increased from 90k to 270K. Due to changes in Struts, I have to modify my example several times, but I don't guarantee that my example works with Struts you downloaded. ☆ Does the correct abstract level Struts provide the correct abstraction level? What is the correct abstraction level for web designers? This is a problem with the text with $ 64K. In the development of a web page, should we let the web designers visited the Java code? Some frameworks (such as velocity) should not, but it provides another web development language to make us learn. Restrict access Java in UI development has certain rationality. Most importantly, if web designers use a little Java, he will use a lot of Java. In the development of Microsoft ASP, I always see this situation. In ASP development, you should create a COM object, then write a small amount of ASP scripts to link these COM objects. However, ASP developers will use ASP scripts crazy. I will hear this, "Since I can write COM objects with VBScript, why should I wait for COM developers to create it?" By using the tag library, Struts helps limit the Java code required in the JSP file. Quantity. Logic Tag is a library that manages conditionally generated output, but this does not prevent UI developers from fanatizing the Java code. Whether you decide which type of framework you want to use, you should know the environment you want to deploy and maintain the framework. Of course, this task is really difficult to do. ☆ Limited Scope Struts is a web-based MVC solution, so you must implement it with HTML, JSP files, and servlets. ☆ J2EE App Support Struts requires support for JSP 1.1 and Servlet 2.2 specification for servlet containers. This is far from which you can solve all your installation issues unless Tomcat 3.2 is used. I am installing this library with Netscape Iplanet 6.0, I encountered a lot of problems, and it is the first application server that meets J2EE. I recommend that you access the archive of the Struts user mailing list when you encounter problems (see Reference Resources). ☆ The complexity is also introduced into several parts of the problem into several parts. There is no doubt that you must understand that struts must accept certain training. As the changes continue to join, this is sometimes very frustrating. Welcome to this website. ☆ Where is it ... I can still point out other issues, for example, where the controller's client verification, how can workflow and dynamic policy mode? However, this is now too easy to become a problem of phenomenon, some problems are irrelevant, or these issues should be issued for 1.0 issues. With the continuous efforts of the Struts team, Struts may have these features when you read this article, or it will have these features soon. Struts's prospects in this new era development, everything has become very fast. In less than five years, I have witnessed from CGI / Perl to ISAPI / NSAPI, and then use VB's ASP, until the current Change of Java and J2EE. Sun is trying to reflect new changes to the JSP / Servlet architecture, as they are the same as the change made by the Java language and the API. You can get a new draft of JSP 1.2 and Servlet 2.3 specification from Sun's website.</p></div><div class="text-center mt-3 text-grey"> 转载请注明原文地址:https://www.9cbs.com/read-54266.html</div><div class="plugin d-flex justify-content-center mt-3"></div><hr><div class="row"><div class="col-lg-12 text-muted mt-2"><i class="icon-tags mr-2"></i><span class="badge border border-secondary mr-2"><h2 class="h6 mb-0 small"><a class="text-secondary" href="tag-2.html">9cbs</a></h2></span></div></div></div></div><div class="card card-postlist border-white shadow"><div class="card-body"><div class="card-title"><div class="d-flex justify-content-between"><div><b>New Post</b>(<span class="posts">0</span>) </div><div></div></div></div><ul class="postlist list-unstyled"> </ul></div></div><div class="d-none threadlist"><input type="checkbox" name="modtid" value="54266" checked /></div></div></div></div></div><footer class="text-muted small bg-dark py-4 mt-3" id="footer"><div class="container"><div class="row"><div class="col">CopyRight © 2020 All Rights Reserved </div><div class="col text-right">Processed: <b>0.041</b>, SQL: <b>9</b></div></div></div></footer><script src="./lang/en-us/lang.js?2.2.0"></script><script src="view/js/jquery.min.js?2.2.0"></script><script src="view/js/popper.min.js?2.2.0"></script><script src="view/js/bootstrap.min.js?2.2.0"></script><script src="view/js/xiuno.js?2.2.0"></script><script src="view/js/bootstrap-plugin.js?2.2.0"></script><script src="view/js/async.min.js?2.2.0"></script><script src="view/js/form.js?2.2.0"></script><script> var debug = DEBUG = 0; var url_rewrite_on = 1; var url_path = './'; var forumarr = {"1":"Tech"}; var fid = 1; var uid = 0; var gid = 0; xn.options.water_image_url = 'view/img/water-small.png'; </script><script src="view/js/wellcms.js?2.2.0"></script><a class="scroll-to-top rounded" href="javascript:void(0);"><i class="icon-angle-up"></i></a><a class="scroll-to-bottom rounded" href="javascript:void(0);" style="display: inline;"><i class="icon-angle-down"></i></a></body></html><script> var forum_url = 'list-1.html'; var safe_token = 'jBqeYYSEXpw_2FJXisEjmlF_2FKMFJVRyEv8JY0S4Ft6xpnijcJPPvSX3qYnzCm66Bk3XpoaIXBLl_2Bw0uErI7KbS_2FQ_3D_3D'; var body = $('body'); body.on('submit', '#form', function() { var jthis = $(this); var jsubmit = jthis.find('#submit'); jthis.reset(); jsubmit.button('loading'); var postdata = jthis.serializeObject(); $.xpost(jthis.attr('action'), postdata, function(code, message) { if(code == 0) { location.reload(); } else { $.alert(message); jsubmit.button('reset'); } }); return false; }); function resize_image() { var jmessagelist = $('div.message'); var first_width = jmessagelist.width(); jmessagelist.each(function() { var jdiv = $(this); var maxwidth = jdiv.attr('isfirst') ? first_width : jdiv.width(); var jmessage_width = Math.min(jdiv.width(), maxwidth); jdiv.find('img, embed, iframe, video').each(function() { var jimg = $(this); var img_width = this.org_width; var img_height = this.org_height; if(!img_width) { var img_width = jimg.attr('width'); var img_height = jimg.attr('height'); this.org_width = img_width; this.org_height = img_height; } if(img_width > jmessage_width) { if(this.tagName == 'IMG') { jimg.width(jmessage_width); jimg.css('height', 'auto'); jimg.css('cursor', 'pointer'); jimg.on('click', function() { }); } else { jimg.width(jmessage_width); var height = (img_height / img_width) * jimg.width(); jimg.height(height); } } }); }); } function resize_table() { $('div.message').each(function() { var jdiv = $(this); jdiv.find('table').addClass('table').wrap('<div class="table-responsive"></div>'); }); } $(function() { resize_image(); resize_table(); $(window).on('resize', resize_image); }); var jmessage = $('#message'); jmessage.on('focus', function() {if(jmessage.t) { clearTimeout(jmessage.t); jmessage.t = null; } jmessage.css('height', '6rem'); }); jmessage.on('blur', function() {jmessage.t = setTimeout(function() { jmessage.css('height', '2.5rem');}, 1000); }); $('#nav li[data-active="fid-1"]').addClass('active'); </script>