Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to analyze simplified Java EE development

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

How to analyze simplified Java EE development, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain for you in detail, people with this need can come to learn, I hope you can gain something.

Java EE is a very complex thing and is regarded as a behemoth by many developers. In the following article, javaonejcy explores how to simplify unnecessary complexities in Java EE development and presents an architectural model that does not use any framework.

You can say cute php, cute ror, cute python, or even cute .net, but Java EE? He's too complicated. Compared with the other two technologies, Java EE's technology system is more comprehensive, more regular and more complex, and its complexity has stopped many manufacturers, preferring to choose simple or even crude php, which fully shows that rapid development is the most urgent need of this era.

Java EE's servlet, javabean, jdbc specifications give us the only standards for components and containers, while more advanced support, jsf, jdo specifications do not give us the only framework-level standards, they are far less recognized than open source frameworks in the same field. Although the open source community gives us the richest choices, Java EE developers must DIY compared to. Net, php, and ror full-stack services. DIY takes not only time but also risk-taking, something that enthusiasts do that companies don't want to do. For some time, the company's Java EE recruitment almost uniformly requires the ability of several mainstream frameworks such as struts, spring and hibernate to prove it.

Java EE development often can not avoid the configuration journey, although many frameworks have automatic generation tools, but in the face of a medium-sized project, it is still easy to cause confusion. Configuration allows you to configure both sides of the code whether you are developing, testing, integrating, or maintaining. Configuration gives the framework an entry point to inject services, but there is no elegance to people. Ror enlightens us that although enterprise development is complex, most of the requirements are generic, and it turns out that ror abstracts this part of generality well in a conventional way. In fact, Java EE is not short of conventions, because it is based on a series of specifications, and specifications are conventions. As a result, Java EE actually has the opportunity to become a relatively concise development technology, but for a variety of reasons, this specification has not emerged.

Among the many Java EE development frameworks, struts+spring+hibernate has the reputation of a golden combination, which is used by many people and will be used by many people. Even students who are not out of school know the importance of learning ssh. But learning and understanding are two different things. For a medium-sized project, ssh has become a double-edged sword, which requires high-level designers to lead the way. Spring+hibernate gives designers a broad space, and the design needs to evolve with the progress of the project. If your project schedule is tight and manpower is insufficient, it will be difficult to guarantee the design quality and bring hidden dangers to the system.

Any good language can help developers write good code, but it can't stop developers from writing bad code. At this point, no matter Java EE, .net, ror, php is no exception. The development framework is like "a house with many beams". "the strength of the framework is not what he can ask you to do, but what he can't ask you to do." in fact, like the language, although the framework can give developers a certain degree of normative guidance, but this guidance is still limited, which really corresponds to the old saying: everything is man-made.

Try to explore how to simplify unnecessary complexity in Java EE development, and give an architecture model that does not use any framework. Let's see whether the combination of structural design and usage can meet the main needs of project development-short-term training, reduction of hidden dangers and rapid development only by using coding conventions.

The source of the problem

Application software development is complex, but its basic model is simple, request-processing-response. The hierarchy corresponding to the software is: request-Cortrol (C); process-Model (M); response-View (V). In early Java EE applications, servlet was in charge of C, javabean and jdbc were in M, and jsp was V. These are the infrastructure of Java EE, and the way in which their responsibilities are divided is called JSP Model2, which can already meet the basic needs of web development. Java EE development has always revolved around these major technologies, and the framework is no exception. The following content will start with the applications and shortcomings of these technologies, then introduce the solutions of the mainstream framework, and then introduce how we deal with them without the framework.

(C) Select Controller

The deficiency of the basic specification

For any web application, it is necessary to return the response after processing the request. If the coding specification is specified, the traditional response is to go to a certain page. There are two ways to turn servlet processing, among which request redirection hides the problem of repeated submission, response redirection brings the problem of encoding and decoding of parameter transmission, and it is also very inelegant for many redirection addresses to be written directly in servlet. In addition, jsp and javabean have an excellent association technology. It is in jsp that the data from the request form can be automatically assembled into javabean. Unfortunately, such a useful technology cannot be used in servlet, so Model2 lacks automatic conversion of form data. It is easy to understand that servlet has these shortcomings, because servlet is, after all, an early technology, and his job is to convert (http) requests into object-oriented views and output responses, and because he is a low-level component, the lack of some functionality is normal. But that makes servlet the weakest link in Model2.

Solution to the development framework

Because the above requirements are common, writing a general framework has become an effort by many people, and struts is quickly launched and popular. Let's first take a look at the features of struts:

Front-end controller: struts uses a servlet as the front-end controller, and all requests go through here before dispatching to the configuration-specified action (in this case, behavior, not specific Action). The intention is to decouple the view layer from the control layer with a middle tier, which brings three possible benefits: 1 View and control separation, so you can choose different view technologies, such as view templates can both use jsp You can also use Volecity or FreeMarker 2 all requests can be preprocessed and post-processed (webwork), and 3 the redirection address of the response can be managed. The front-end controller also has a direct deficiency: tedious configuration.

ActionForm: struts is mainly a control layer framework, so he does not intend to go deep into the model layer. ActionForm is a helpless choice. Although it provides the conversion of form data to javabean, it is a pity that this javabean can not be used directly, and it has to be manually converted to model javabean, which makes the position of ActionForm somewhat awkward.

Internationalization support, tag libraries, and global exceptions: internationalization and tag libraries are the highlights of struts, but global exceptions are limited.

Our choice.

The controller of the Java EE must be a servlet, and we are no exception, because we have to run in the servlet container. However, we chose the evolved version of servlet-jsp. Don't get me wrong, we're not going back to JSP Model1. A typical example is that if I have a function point for employee information entry, in order to achieve this function, I can create the following two files:

Worker_input.jsp

Worker_inputOper.jsp

No control code is written in worker_input.jsp, and no view code is written in worker_inuptOper.jsp, which is actually a combination of JSP Model1 and JSP Model2. The biggest advantage of this is that you don't have to worry about configuration, but wait. What about the front controller? Where's our middle floor?

Consider that you have a form of enterprise information. There is an enterprise name field in the form. The requirement for this field is that you cannot repeat the name in an existing enterprise. There is a button next to the field. The salesman can click this button to get a hint as to whether the enterprise name is duplicated. If it is the traditional way, clicking the button will result in a page submission. If you use struts, you will configure the URL address to be redirected after the action processing. This is the response of traditional web applications-page navigation based on URL address.

Web2.0 is coming, ajax is coming, and the emergence of asynchronous requests has completely subverted the traditional web interaction model. For ajax applications, the server only needs out.print to return the response, and the tasks of where the request comes from, where to go, where to redirect (if necessary), and to update the view are left to client script, that is, web applications based on asynchronous interaction mode have no result URL path to configure at all. In this way, the problem of page navigation is solved automatically. For preprocessing, we can use filter instead. So we can say goodbye to the front controller.

Due to the trend of client technology, we will fully use ajax in webappdemo. You might say, what if client browsers disable scripting? This worry is no longer necessary these days, you can visit Happy or Dangdang to see if they can work with disabled scripts. With the progress of the times, rich customer RIA is the inevitable choice.

Using jsp as the controller also gives us another key feature, which is the automatic creation and input of data from form forms to javabean, so that javabean itself is both a model and a DTO, eliminating the need for manual transformation like ActionForm. There is also an implicit benefit of forcing the unification of the form domain name and the model property name, otherwise it is possible that the form field: child_center; the model property: branch. Here is how to write worker_inputOper.jsp:

Jsp code

< jsp:useBean id="worker" class="webappdemo.worker.entity.Worker" scope="page"/>

< jsp:setProperty name="worker" property="*"/>

< % response.setContentType("text/x-json;charset=UTF-8"); response.setHeader("Cache-Control", "no-cache"); String method = request.getParameter("method"); if("save".equals(method)){ EntityService es = new EntityService(); Message m = es.add(worker); out.print(new JSONObject().put(m.isSucceed()?"succeed":"error", m.getMessage())); return; } %>

As you can see, we can get an automatically assembled Worker object simply by introducing the entity class name into the tag. For complex objects or composite objects, because request also has all the request parameters we need, you can modify some properties based on the automatically created javabean to meet business needs.

The code also shows the use based on "method", which is just a string that tells oper jsp which method to use to handle the request, which is similar to the method defined internally by the ror controller and struts's DispatchAction, but is more flexible than him, and flexibly solves the deficiency that the jsp request can not be directly oriented to the method.

After invoking the service to process the request, worker_inputOper.jsp out.print the processing result back to the client. This code means to create a new JSON object, add the processing result, and then output the object to facilitate client js script parsing. JSON objects can add multiple processing results, as long as their key is different. In practical applications, it is common to return a processing message, or a string for the html view. Finally, don't forget return; or the program will still go down.

If your project needs to be internationalized, we can use the fmt tag, and for the internationalization of feedback messages, we may need to create a global MessageSource object, which is not covered in webappdemo, because I don't think this is a general requirement.

For exception handling, jsp already provides a simple mechanism, which we can configure in web.xml:

Xml code

< error-page>

< error-code>

four hundred and four

< /error-code>

< location>

/ 404.jsp

< /location>

< /error-page>

< error-page>

< error-code>

five hundred

< /error-code>

< location>

/ 500.jsp

< /location>

< /error-page>

This simple handling is actually all we need, because the author believes that there is no difference between web application system errors and java exceptions, that is, detection errors and run-time errors. In the age of web2.0, all errors should be caught and the content should be processed and fed back to the user at the user's input location, rather than redirected. Run-time errors belong to the system bug and are code-level errors that need to be fixed. This kind of error is really "unexpected", so we can just feedback it to the user with a customized error page.

To sum up, we use ajax+jsp+ to control jsp instead of servlet or action, get rid of the front-end controller, and use model javabean instead of process javabean ActionForm, which enables us to develop applications without configuration. Besides ajax is a relatively new concept, it is also his advantage that we do not need to learn the framework technology.

(M) what can ORM do?

The deficiency of the basic specification

Jdbc is not only the basis of data persistence in java applications, but also the interface between many database vendors and java. Writing code directly using jdbc is very tedious, such as the acquisition and release of database resources, exception capture and transaction processing, etc., repetitive code is one of his characteristics. In addition, different databases, in the data type, primary key type or sql statement are slightly different from the SQL standard, so how to make the application can be easily migrated in different database platforms is also a problem.

Solution to the development framework

The emergence of spring and hibernate has greatly improved the situation. Spring manages transactions in aspects, hibernate automatic ORM can greatly simplify development, and both spring and hibernate have .net versions, which proves their success. However, "to make good use of hibernate, we need to firmly master the relational model and SQL". At the same time, we should also have a very clear understanding of object-oriented design and the operating mechanism of hibernate itself. only at this level can we give full play to the power of hibernate and reduce the risks brought by hibernate. Therefore, configuring the transaction management of spring on an appropriate level, designing the object model and controlling the direct use of hibernate within a certain range are the basic problems that designers need to solve. If the design is not good, or directly handed over to the developers who are just out of school, then this combination will become a scourge and is not conducive to the growth of team members.

Our choice.

If there is only jdbc, our system can also work, but we have to write a lot of repetitive and mechanical code. Through the mapping of the ORM of the framework, the data of database tables can be automatically filled into javabean, which saves labor and makes the structure of the system natural and clear. If we don't use ORM tools, can we simulate his behavior in some way? We can create an interface like this:

Java code

Public interface IOper {boolean load (Connection connect) throws SQLException; boolean add (Connection connect) throws SQLException; boolean update (Connection connect) throws SQLException; boolean delete (Connection connect) throws SQLException;}

Define the CRUD method in the interface. The return type is boolean rather than the number of rows affected, and the intention is that the operation within the object may be complex and multi-step, so for its upper application, it is OK to know whether the result is successful or not. Next, you can write this in his implementation class:

Java code

Public class Worker implements IOper {/ / Fields private Integer workerId; private String workerName; private String logonName; private String logonPwd; / * * assign initial values to fields that are allowed to be empty to prevent the page from displaying null * / private String mobile = "; private String email ="; private String remark = "" Private String isFreeze = "0"; / / Constructors / * * default constructor * / Property accessors public boolean add (Connection connect) throws SQLException {SQLBuffer sql = new SQLBuffer (); sql.segment ("insert into worker (worker_name,logon_name,logon_pwd,"); sql.segment ("mobile,email,remark,is_freeze) values (") Sql.value (this.workerName); sql.comma (); sql.value (this.logonName); sql.comma (); sql.value (this.logonPwd); sql.comma (); sql.value (this.mobile); sql.comma (); sql.value (this.email) Sql.comma (); sql.value (this.remark); sql.comma (); sql.value (this.isFreeze); sql.segment (")); return Proxy.update (connect, sql) = = 1 } public boolean delete (Connection connect) throws SQLException {/ / freeze user SQLBuffer sql = new SQLBuffer (); sql.segment ("update worker set is_isfreeze ="); this.isFreeze = "1"; sql.value (this.isFreeze); sql.segment ("where worker_id ="); sql.value (this.workerId) Return Proxy.update (connect, sql) = = 1;} public boolean load (Connection connect) throws SQLException {SQLBuffer sql = new SQLBuffer ("select worker_name,logon_name,logon_pwd,mobile,email,remark,is_freeze from worker"); sql.segment ("where worker_id ="); sql.value (this.workerId) MapRow mr = Proxy.getMapRow (connect, sql); if (mr = = null) {return false;} this.workerName = mr.getString ("worker_name"); this.logonName = mr.getString ("logon_name"); this.logonPwd = mr.getString ("logon_pwd"); this.mobile = mr.getString ("mobile") This.email = mr.getString ("email"); this.remark = mr.getString ("remark"); this.isFreeze = mr.getString ("is_freeze"); return true;} public boolean update (Connection connect) throws SQLException {SQLBuffer sql = new SQLBuffer (); sql.segment ("update worker set worker_name =") Sql.value (this.workerName); sql.segment (", logon_name ="); sql.value (this.logonName); sql.segment (", logon_pwd ="); sql.value (this.logonPwd); sql.segment (", mobile ="); sql.value (this.mobile); sql.segment (", email =") Sql.value (this.email); sql.segment (", remark ="); sql.value (this.remark); sql.segment (", is_freeze ="); sql.value (this.isFreeze); sql.segment ("where worker_id ="); sql.value (this.workerId) Return Proxy.update (connect, sql) = = 1;}}

The entity javabean is responsible for the operation of its own data by implementing the IOper interface. Although this implementation is tantamount to making the model a blood-rich model, we can still think of this model as anemic because it has no business logic and only simulates the behavior of ORM. If object relationships have inclusions and aggregations, we can also do so through hibernate-like behavior, such as lazy loading. The above code uses the API used by the author, and since the operations are all internal, it is the same to use jdbc directly. In practical application, the load method is a little thin, because some queries require some additional conditions, which can be achieved by adding a class attribute:

String condition

If the condition is set, we will splice the given query condition to get the result, but the result can only be one, which is determined by the model structure. In addition, the Connection object is a necessary parameter for each method, and the intention is that in the actual business operation, a single operation often does not exist, so resources are always passed and released from the outside. But isn't it boring to write duplicate try catch and code to get and release connections at every place you call? So, we can wrap it with a service class, which shows the usefulness of the IOper interface:

Java code

Public class EntityService {public Message add (IOper io) {try {Connection connect = Proxy.getConnect (); connect.setAutoCommit (false); / / add if (! io.add (connect)) {throw new Exception ("add operation failed") } / / other operations connect.commit (); return new Message (true);} catch (Exception e) {Proxy.rollbackConnect (); e.printStackTrace (); return new Message (e) } finally {Proxy.closeConnect ();}} public Message update (IOper io) {try {Connection connect = Proxy.getConnect (); connect.setAutoCommit (false) / / modify if (! io.update (connect)) {throw new Exception ("modify operation failed");} / / other operations connect.commit (); return new Message (true) } catch (Exception e) {Proxy.rollbackConnect (); e.printStackTrace (); return new Message (e);} finally {Proxy.closeConnect () }} public Message delete (IOper io) {try {Connection connect = Proxy.getConnect (); connect.setAutoCommit (false); / / Delete if (! io.delete (connect)) {throw new Exception ("delete operation failed") } / / other operations connect.commit (); return new Message (true);} catch (Exception e) {Proxy.rollbackConnect (); e.printStackTrace (); return new Message (e) } finally {Proxy.closeConnect ();}} public Message load (IOper io) {try {Connection connect = Proxy.getConnect (); connect.setAutoCommit (false) / / load if (! io.load (connect)) {throw new Exception ("load operation failed");} / / other operations connect.commit (); return new Message (true) } catch (Exception e) {Proxy.rollbackConnect (); e.printStackTrace (); return new Message (e);} finally {Proxy.closeConnect ();}

As you can see from the EntityService code, try catch should always appear in the service layer, and only a separate service is necessary to guarantee a complete transaction. If you want to record the business log after the CUD operation, you can write it in the location of "other actions". Due to the dependence on external information, such as user information, functional ID and so on, more complex designs are needed in practical applications. At this point, we have completed the simulation of the ORM behavior, and at the place of call, we just need to:

Java code

EntityService es = new EntityService (); Message m = es.add (worker)

Although the code inside the method is still cumbersome, we reduce the complexity by focusing the location of the code on less, and get a good structure at the same time. More intuitive operation of the database is the advantage of "handwritten" code, of course, we can also choose ibatis, but the structure will not be like this. At the same time, the author believes that sql code is always closely related to the inside of the program, so it doesn't seem convenient to configure it externally.

For the problem of database migration, hibernate solves this problem to a great extent, but there is not much need to migrate data in enterprise development, and database migration can not be completely solved by using a certain tool or specification (jdbc, jdo). For large and complex applications, migrating databases requires great efforts, so in fact, no one does so.

(v) client MVC

The instructions on client applications do not have internal segmentation, because Java EE technology (not to mention javafx) itself does not have much to do with the client, so there is no deficiency. Here is just to correct some bad coding habits in the system.

Jsf is the Java EE UI framework specification, front-end controller, event model and UI components are its main components, but the actual development of jsf tags is very cumbersome, and only the client explicitly disable scripts or other components (flex-flash, javafx or even silverlight), jsf is the most valuable, unfortunately (lucky) is that there are few client browsers do not support the above scripts or plug-ins, so the value of jsf has been greatly reduced.

Jsp is a Java EE view component and one of the foundations of the jsf UI framework. It is actually a loose view template. Although this looseness may not be conducive to software layering, it has at least one advantage over other template technologies, that is, it is very similar to asp, which makes it easier for developers to accept. In the era of web2.0, if your project is not going to use flex-flash or javafx, then jsp is your best view carrier, you can put javacript, css, html, xml, json and java code here, in order to achieve the interactive logic of ajax, you may have to write large chunks of javascript, it doesn't matter, jsp can handle it, although these things together look like a mouse nest.

The authors of Ajax in action put forward the concept of client-side MVC, but don't get me wrong, this is not the development model of ext or flex, but just an idea. Html is a view structure established by the dom tree, so M, css adds effects to the html structure, so V, javascript controls the display logic, which means C, the client MVC refers to the three language code to establish separate files, referencing external css and js in the html page. Similarly, taking the input of employee information as an example, we can create the following documents:

Worker_input.jsp

Worker_inptu.js

Style.css

As you can see, we do not name css files in a functional way, because stylesheets can often be shared by the whole system, that is, we just need to remember not to write css, js code in html, and create js files separately. Creating separate files for different types of code is a key step in improving the readability of the code, especially at a time when client programs are becoming more complex. Worker_input.js writes like this:

Js code

/ / Save function save () {if (check ()) {AjaxUtil.sendForm (document.forms [0], "method=save", function () {if (this.result.succeed) {document.forms [0] .reset (); messageapp.printMessage (this.result.succeed)) } else if (this.result.error) {messageapp.printMessage (this.result.error);}}, true);}}

This file defines only one save method, which initiates an ajax asynchronous request internally. If it returns successfully, it resets the form and updates the output information to the specified location, otherwise only the output information is updated. You will notice that the JSON object we returned worked.

Question: if this happens in my jsp code, is it against the principle of client-side MVC?

Html code

< tr>

< td colspan="2">

< input type="button" value="保 存" onclick=save();"/>

< input type="reset" value="重 置" />

< input type="button" value="返 回" onclick=window.history.go(-1);" />

< /td>

< /tr>

There are brief js code and method references in the above code snippet. In this case, the author thinks it is OK. There is no need for project development to pursue absolute perfection, as long as the goal of a clear structure is achieved. We want high-quality products, not high-quality theories.

Question: if I use a script tag library like ror's JavaScriptHelper, and the generated script is mixed with html code, is this against the client-side MVC principle? Obviously, it doesn't count, because for the jsp code template before output, the program structure is clear.

(F) structure and details

With regard to the introduction of various parts of MVC, let's take a look at the overall structure. Suppose we are in an eclipse project and open the WebRoot directory. If we ignore the META-INF and WEB-INF directories, our example directory looks like this:

Module

404.jsp

500.jsp

Index.htm

Module is where we apply all the views, because of the way we use jsp, including all the controllers. Applications are placed in one directory to facilitate directory protection or some other preprocessing using filter in the future. Open the module directory and the structure is as follows:

Common worker

A common directory for all shared program files, and a worker directory for functional files about the employee entity. In fact, your structure may also be sys/worker or center/sys/worker, etc., depending on the actual application requirements, in short, through the directory division of functional modules, with the correct tree structure to describe it is correct. Let's open the common directory again:

Css img js import_page.def

The first three directories hold common files, while the last one is a file, which will be added to the jsp header of each view in this way.

< head>

< /head>

Add:

Jsp code

< %@ include file="../common/import_page.def"%>

Relative paths are used here, and this file is added to make it easy to reference other css and js library files. In this way, you can avoid the trouble caused by merging js or making version changes to css or js library files during the deployment phase.

Let's look at the directory structure of java src:

Webappdeom common worker datasource.xml log4j.properties

Except for the root directory, it is consistent with the structure under WebRoot. Two files: datasource.xml is the data source configuration file, which is also needed by the API used in the author's demo, and log4j.properties is the property file of log4j. In addition, the system uses hsql database by default. If you want to start normally, you need to change a configuration item in web.xml. The specific location is annotated.

Then the specific structure and code will not be said here, if you are interested, you can download webappdemo to have a look, the comments inside are more complete. However, there are some hidden problems in demo, as well as ideas that can be expanded. I don't know if you can find them.

Is it helpful for you to read the above content? If you want to know more about the relevant knowledge or read more related articles, please follow the industry information channel, thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report