Intellectual health
Project introduction
Business system of health management organization
Traditional Internet projects (back-end system, front-end wechat web page)
Information that developers should need
1. Requirements specification PRD [including function outline, function details, flow chart, performance requirements], product prototype diagram
2.UI: the prototype drawing is not the final effect drawing, and the UI shall prevail. So if you have it, you need to get it
3. Interface name and other parameters for interfacing with front-end staff
development process
-
Demand analysis: the product personnel do and output PRD (including function outline, function details, flow chart and performance requirements) and product prototype diagram
-
Design (general design and detailed design): the architect does and outputs general design and detailed design (state machine, class diagram, sequence diagram)
-
Coding: programmer, output function code (source code, unit test code of function)
-
Testing: testers, output test reports (test cases [various situations in use], function test reports, performance test reports, security test reports, integration test reports)
-
Operation and maintenance: programmers upgrade and maintain functions
Project structure diagram
-
Project directory structure
-
Project technical support
Problems to be solved
1. Find out the differences among Controller, RestController and ResponseBody (solved)
Project BUG summary
1. Error: version 1.0-SNAPSHOT in the parent project cannot be found
Reason: due to interdependence, the previous dependent package cannot be found during packaging
Solution: first packaging order: domain – > parent project
2. Error reporting: the control layer member variables are normally injected into the space-time pointer
Cause: thread blocking occurred when zk was started
Solution: restart zk and be careful not to stop the cursor. Right click Cancel
3. Error report: business layer member variable injection is null
Most of the things in the business layer are jar packages, so you can inject them directly and automatically
4. Error reporting:
Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type: class com.wz.result.Result
Reason: the returned result cannot be converted to json normally
Solution: json dependent package is required
-
The business layer can obtain the results normally and report an error timeout when returning to the control layer
Reason: network fluctuation is related to your own computer
Solution: add the timeout duration in both the business layer and the control layer
-
Dynamic SQL statement error: Java sql. SQLException: Parameter index out of range (2 > number of parameters, which is 1).
Reasons: 1) comment statements in dynamic sql
2) strings can only be spliced by concat
Solution: where code = #{value} or name like CONCAT(CONCAT('%', #{value}), '%')
<select id="findAllCheckItem" resultType="CheckItem" parameterType="string"> SELECT * FROM t_checkitem //Note: the value here must be consistent with the getvalue method name of string. If you want to use other names, use @ param to specify the variable name <if test="value!=null and value.length>0"> where code = #{value} or name like CONCAT(CONCAT('%', #{value}), '%') </if> ORDER BY id DESC </select>
7.sql error, Duplicate entry 'xxx' for key 'PRIMARY'
Reason: when operating the database, the primary key of the same data is added or deleted (in the same transaction)
Solution: check whether the logic or sql statement is consistent with the logic
8. Foreground status code 400 background HTTP conversion failed
Reason: the parameters transmitted from the foreground to the background must be consistent with the background @ RequestBody, otherwise an error will be reported
Solution: pass in the parameters required by the background
9. Front end 415 error, not application/json type
Cause: caused by dependency package error
Solution: use the complete json type dependency package
10. When using hashmap of freemaker for storage, you cannot use object to store entity class objects, which will lead to map Put cannot encapsulate an entity class in an entity class
11.interval = window.setInterval(timer,100); Method, the caller method cannot be timer(), otherwise it will be executed only once!!
12. Everything is normal. The permission has been set and confirmed to be removed, but the removed permission can still be operated normally.
Reason: use hasAuthority instead of hasPermission.
Solution: when setting permissions with annotations in the background, use hasAuthority instead of hasPermission.
@PreAuthorize("hasAuthority('CHECKITEM_EDIT')")
13. (followed by a bug) the user does not have the permission but is not blocked and can still be used
Reason: when using spring security security framework, web XML configuration files cannot be scanned at the same time, which will lead to ineffective permissions.
Solution: use the dispatcher scanner to scan all configuration files directly, and you can't use the import tag to import in spring
Summary of project precautions
1. If a dependency that must be inherited is specified in the parent project, it cannot be specified in the child project, otherwise an error will be reported.
2.web. Tags in XML exist in order
3. The bottom layer of Dubbo annotation scanning package will automatically scan component and its sub annotations, so spring scanning package can not be used
[it is recommended to add spring package scanning, because an error will be reported if other spring annotations need to be used]
4. Set Web The XML access path is / must be configured with static resource filtering
5. dao objects in the business layer can only be injected automatically in the way of autowarned, not remotely, otherwise they are null
6. Question: why is new not automatically injected when ssm result object is used?
Not all classes should be managed by the container. Classes created frequently like this are handed over to the container, and the container will crack.
Why is dao not divided into three-tier architecture?
A: it is not necessary to re decompose the network resources occupied by one layer
7. Since the post method is used, you must use @ RequestBody on the parameters of the method to inject automatically
8. The difference between $# of sql statement in Dao: # add '# when compiling, and the other will not. What value is passed will be stored without' [high frequency interview]
9. If the dao is garbled when writing to the database, splice '? characterEncoding=utf8’
10. When @ Service and @ Trasactional are used together in the business layer, you need to specify Interfaceclass or interfaceName for @ Service and generate entity objects in zk for access
11. Why can we use requestBody on the back end to connect json data normally? Because the application/json is specified in the contentType of the front-end page, the bottom layer of the annotation helps us specify it, so we can
12. Most of the front-end methods are asynchronous methods.
13. When using JDBC configuration file, you must add an enhanced suffix to the url item.
14. If the parent class framework is used for remote call, it must be injected with the set method of the member variable, otherwise it will not take effect and will be null
15. When querying mybatis, the total of the query is 1, but the actual query in mybatis is 0, but this 0 is still a record, so the total is 1
16. Trilogy of verification rules
1. Input process verification
2. Submit form verification
3. Background verification background verification if you need to use network remote transmission, such as dubbo, it is written in the control layer. The rest can be in the business layer, which is convenient for packaging and reuse.
- Each table must have a clear field meaning!
18. If the value in redis has an expiration time, the redis key still exists after expiration. I just can't get the value of this key. There is a 200ms scheduled cleaner at the bottom of redis to clean up these expired keys
19. In the insert sql statement of mybatis, useGenerate=true keyproperty = "table field name" can replace selectKey to obtain the primary key
Project solving skills
1. If you encounter a jar package conflict, you can choose to delete the updated file of the corresponding jar package (it is recommended to delete all the updated files in the local warehouse)
2. When using transactions in dubbo, the attribute interfaceClass = class name should be used in the service annotation of the business layer Class definition. If it is not defined, the proxy object will be found in zk's registry. Only after it is defined will there be such an object with the same package name in the registry
3.VUE built-in output spring frame this$ message. error/success/info(" ") ;
4. The front-end code has more than one post request parameter, which can be added after the method? It is transmitted in the form of get, and the back end receives it with multiple parameters,? The parameters after are received without @ RequestBody json
5. Search the Maven project on Baidu. The dependency package starts with Maven. The dependency package can be found quickly after
6. In vue, you can assign values to objects of type {} by using ['key']. As a key, it exists with overwrite and no creation. This is a js syntax
if(vali) { //Verification rules let temp = []; //Store temporary variables this.checkitemIds.forEach(item => { //Check item with variable checked temp[temp.length] = {'id': item}; //Since the index is 0, the index length is + 1 for each element added }); this.formData['checkItems'] =temp; //Complete assignment // As long as it is an object type, you can use [] for assignment, with overwrite and no creation } //Complete assignment // As long as it is an object type, you can use [] for assignment, with overwrite and no creation
7. Use freemaker
Precautions: 1 Each loop variable of the required placeholder cannot be empty
2. Placeholder symbols cannot be misspelled
Project specification
1. All exceptions are uniformly received and handled by the control layer. It is better to encapsulate a class to return uniformly
2. If there is string information, try to use static final class to define the call instead of direct hard coding
3. Trilogy verification. The last step is controlled at the control layer to avoid the impact of dubbo remote verification at the business layer on efficiency
Source code analysis
1. The Dubbo package scanning tag will load the Component annotation at the bottom, so if it is only applicable to components, it can be used without using spring package scanning [component is actually the parent of controller, service and repository]
2. If you want to inject private member variables in the parent class, AutoWare supports injection in the parent class
However, remote injection using dubbo is not allowed, because the source code is limited, and remote injection can only be carried out by the method starting with the set method
Therefore: define member variables and use the set method to realize injection
3. Every time ZK is used, the node of dubbo will be generated. If interfaceName (full pathname) / interfaceClass (class name). Class) is not specified, it will?
4. There are two ways to get parameter names at the bottom of mybatis
@Param and / / parameter names. If annotations are not used, the JVM will first try to use this name at the bottom If the class file is found, it can be used. If it is not found, it will be parsed with the name arg0 arg1. Whether it can be found is related to the computer.
Unified specification. Annotation should be used when using a single variable name
5. The bottom layer of the start method of PageHelper paging plug-in is the threadLocal shared memory area
Therefore, when searching the method, you will go to the shared area to get the seemingly irrelevant current page and the size of each page
Then, the limit keyword will be added to mybatis for query
Phase I – back office development
Development module function
1) Check item / group management module
Import databases and forms
The character set must be specified when creating the database utf8mb4 Function: support when using mobile terminal emoj Four characters
Use PMD to explain the meaning and operation of each field in each table (specification)
The database table varchar (32) stores 32 letters, 16 characters (2 bytes) and 8 expressions (4 bytes)
Import entity class
Import public resources
1. Returns the status type object of the front end
2. Returns the result object of the front end
3. Paging object [total number, current page result]
4. Query objects by criteria
5. Basic static resources
PowerDesigner tabulation design
View the PDF of the first day of the project and the specific steps
Is an ER entity relationship diagram design software, referred to as PDM (database design diagram)
It is convenient to analyze and design the system, so as to make data flow chart, physical data model (database table design), conceptual data model and object-oriented model.
1. Tabulation process
Mysql 5.0 should be used to create tables, otherwise sql yog creation will report an error
code – indicates table name and field name
p -- primary key
identity – self increment of primary key
2. Export sql table
Foreign keys should be specified in the design, but they are filtered out when creating the database
1. database in menu bar
2.create database
3. Option -- > uncheck the foreign key
3. Reverse engineering
Parse the table creation file into a table diagram structure and display it on the software
file —reverse --database
4. Generate database report file
Generate a web version of the overall table data is intuitive, you can view the structure or information of all tables in it
report - report wizard
The new datagroup software is easy to use and needs to be cracked
datafactory, stress testing software. Mass production data for database tables
Front end UI design
To use any component, you need to create an object first
new Vue ({
el : " "
})
Layout container
General layout of container
Resolution:
In el - main, the remaining page space of the current row is automatically filled
The attribute definition of the container is one line for each child tag
If you want to keep aside and main in the same line, you need to use container to store them together
The side on the left and right are set in the order of sub labels
<!--Import previous vue Component can take effect--> <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css"> <script src="element-ui/vue.js"></script> <!-- introduce ElementUI Component library --> <script src="element-ui/lib/index.js"></script> <el-container> <el-header>Header</el-header> <el-container> <!--It can be left placed in the same container--> <el-aside width="200px">Aside</el-aside> <el-container> <el-main>Main</el-main> <el-footer>Footer</el-footer> </el-container> <!--It can be placed right in the same container--> <el-aside width="200px">Aside</el-aside> </el-container> </el-container>
drop-down menu
Objective: to learn the properties and types that components focus on
size
trigger
divided in the sub label can add a dividing line to each sub option
<el-container> <el-aside width="200px"> <el-menu> <el-submenu v-for="menu in menuList" :index="menu.path"> <template slot="title"> <i class="fa" :class="menu.icon"></i> {{menu.title}} </template> <template v-for="child in menu.children"> <el-menu-item :index="child.path"> <a :href="child.linkUrl" target="right">{{child.title}}</a> </el-menu-item> </template> </el-submenu> </el-menu> </el-aside> <el-container> <iframe name="right" class="el-main" src="ordersetting.html" width="100%" height="580px" frameborder="0"></iframe> </el-container> </el-container>
<script> new Vue({ el: '#app', data:{ menuList:[ //Cycle the menu to display the corresponding data and jump function { "path": "1", "title": "workbench", "icon":"fa-dashboard", "children": [] }, { "path": "2", "title": "Member management", "icon":"fa-user-md", "children": [ { "path": "/2-1", "title": "Member files", "linkUrl":"member.html", "children":[] }, { "path": "/2-2", "title": "Upload physical examination", "children":[] }, { "path": "/2-3", "title": "Membership statistics", "linkUrl":"all-item-list.html", "children":[] }, ] }, { "path": "3", "title": "Booking Management ", "icon":"fa-tty", "children": [ { "path": "/3-1", "title": "Subscribe List ", "linkUrl":"ordersettinglist.html", "children":[] }, { "path": "/3-2", "title": "Reservation settings", "linkUrl":"ordersetting.html", "children":[] }, { "path": "/3-3", "title": "Package management", "linkUrl":"setmeal.html", "children":[] }, { "path": "/3-4", "title": "Inspection team management", "linkUrl":"checkgroup.html", "children":[] }, { "path": "/3-5", "title": "Inspection item management", "linkUrl":"checkitem.html", "children":[] }, ] }, { "path": "4", "title": "Health assessment", "icon":"fa-stethoscope", "children":[ { "path": "/4-1", "title": "TCM Constitution identification", "linkUrl":"all-medical-list.html", "children":[] }, ] }, { "path": "5", //Route path corresponding to the menu item "title": "statistical analysis", //Menu item name "icon":"fa-heartbeat", "children":[//Whether there is a submenu. If not, it is [] { "path": "/5-1", "title": "Workload statistics", "linkUrl":"all-medical-list.html", "children":[] } ] } ] } }); $(function() { var wd = 200; $(".el-main").css('width', $('body').width() - wd + 'px'); }); </script>
Navigation menu
View on the official website
Message message prompt
See more on the official website
Built in object this$ Message is activated using the event success/erorr/info/warning
Here, take the callback function as an example
axios.post("/Jump",this.formData).then((resp)=>{ //Judge callback result //If the result is true if(resp.data.flag){ //Prompt, successful this.$message.success(resp.data.message) ; //Use pop-up built-in objects //Refresh the page to display all the data of the inspection items this.pagination.currentPage=1; this.findPage(); }else { //Prompt, error this.$message.error(resp.data.message) ; //Refresh the page to display all the data of the inspection items this.pagination.currentPage=1; this.findPage(); } })
form
Table component functions
Template slot scope = "'scope' scope slots are defined in the sub label template
//1. Set row fixation //2. Zebra stripes //3. Bidirectional binding of datalist variables <el-table size="small" current-row-key="id" :data="dataList" stripe highlight-current-row> <el-table-column type="index" align="center" label="Serial number"></el-table-column> <el-table-column prop="code" label="Item code" align="center"></el-table-column> <el-table-column prop="name" label="entry name" align="center"></el-table-column> <el-table-column label="Applicable gender" align="center"> <template slot-scope="scope"> <span>{{ scope.row.sex == '0' ? 'unlimited' : scope.row.sex == '1' ? 'male' : 'female'}}</span> </template> </el-table-column> <el-table-column prop="age" label="Applicable age" align="center"></el-table-column> <el-table-column prop="remark" label="Project description" align="center"></el-table-column> <el-table-column label="operation" align="center"> <template slot-scope="scope"> <el-button type="primary" size="mini" @click="handleUpdate(scope.row)">edit</el-button> <el-button size="mini" type="danger" @click="handleDelete(scope.row)">delete</el-button> </template> </el-table-column> </el-table>
-
Zebra stripe different color
-
Change of background color: row class name = "tableRowClassName"
//Provide method to change color tableRowClassName({row, rowIndex}) { if (rowIndex === 1) { return 'warning-row'; } else if (rowIndex === 3) { return 'success-row'; } return ''; } }
-
The header is fixed, and the height of the table can be set. Height = "250"
-
Column fixed / frozen. Set fixed on the column. If it is right fixed, it is fixed = 'right'
-
Table generation sequence number
<el-table-column type="index" width="50"></el-table-column> // type="index"
-
Radio highlight current row for table columns
-
Multiple selection of tables
<el-table-column type="selection" width="55"> </el-table-column>// type="selection"
-
The table is sorted by column header, and sortable can be added
label
View on the official website
form
Layout of forms
Verification of forms
1. Real time verification
2. Submit verification
//Define validation rules in the data attribute //Validate rules in form <!--Set reference name, bidirectional binding formdata Form content, specifying rules--> <el-form ref="dataEditForm" :model="formData" label-position="right" label-width="100px" :rules="rules"> rules: { name: [ { required: true, message: 'Please enter the activity name', trigger: 'blur' }, { min: 3, max: 5, message: 'The length is between 3 and 5 characters', trigger: 'blur' } ], region: [ { required: true, message: 'Please select an active area', trigger: 'change' } ] } //Syntax for input verification this.$refs['form'].validate(function(valid){ }); //Clear check this.$refs["dataAddForm"].resetFields(); this.$refs["dataAddForm"].clearValidate();
3. Form division
The form can be divided into 24 copies and the length can be defined separately
<el-form ref="dataEditForm" :model="formData" label-position="right" label-width="100px" :rules="rules"> //This behavior is a group and bound with the span attribute of the column label. It is recommended to divide it with 24 as an integer <el-row> <el-col :span="12"> <!--Set verification object--> <el-form-item label="code" prop="code" > <el-input v-model="formData.code"/> </el-form-item> </el-col> <el-col :span="12"> <!--Set verification object--> <el-form-item label="name" prop="name"> <el-input v-model="formData.name"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="Applicable gender"> <el-select v-model="formData.sex"> <el-option label="unlimited" value="0"></el-option> <el-option label="male" value="1"></el-option> <el-option label="female" value="2"></el-option> </el-select> </el-form-item> </el-col> <el-col :span="12"> <!--Set verification object--> <el-form-item label="Mnemonic code" prop="helpCode"> <el-input v-model="formData.helpCode"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="explain"> <el-input v-model="formData.remark" type="textarea"></el-input> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="matters needing attention"> <el-input v-model="formData.attention" type="textarea"></el-input> </el-form-item> </el-col> </el-row> </el-form>
Paging component
- sizes, how many pieces per page
- total
- prev
- pager, quick click page number
- next
- jumper, jump page
<div class="pagination-container"> <el-pagination class="pagiantion" //Built in class style @current-change="handleCurrentChange" //Activation method when clicking paging :current-page="pagination.currentPage" //Current page :page-size="pagination.pageSize" //Size per page layout="total, prev, pager, next, jumper"//Clickable buttons :total="pagination.total" //PageCount > </el-pagination> </div> //Method name and content are defined by yourself handleCurrentChange(currentPage) { this.pagination.currentPage=currentPage; //Modify current page this.pagination.queryString=null;//Reset query box content this.findPage();//Call query },
Code generation tool
Function: generate code in DAO layer, with the name of [mybatis generator] (the free mybatis plug-in has integrated this graphical function)
Steps:
1. Import dependencies in build/plugins
2. Create configuration file [in the project that needs to generate code]
3. Connect to database
Seven cattle cloud upload pictures
The image server has a hot image cache and can add a CDN cache (very expensive) to form a set of image response architecture
– upload the web page to your own server, and the server will forward it to the image server. The next visit will be directly obtained from the image server (qiniu)
API usage: help document of qiniu cloud SDK
Usage details:
1. Upload objects and import dependencies in the control layer configuration file
<!--File upload component--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="104857600" /> <property name="maxInMemorySize" value="4096" /> <property name="defaultEncoding" value="UTF-8"/> </bean>
<quartz.version>2.2.1</quartz.version> <commons-fileupload.version>1.3.1</commons-fileupload.version> <!-- File upload component --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>${commons-fileupload.version}</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>${quartz.version}</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>${quartz.version}</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.18.1</version> </dependency> <dependency> <groupId>com.qiniu</groupId> <artifactId>qiniu-java-sdk</artifactId> <version>7.2.0</version> </dependency>
2. Add two necessary methods on the page: check before uploading and display after uploading
//The hook after the file is uploaded successfully. The response is the value returned by the server, and the file is the js object encapsulated by the currently uploaded file handleAvatarSuccess(response, file) { //The response here is the returned result object, which can be used directly attribute this.imageUrl=response.data; this.$message({ type:response.flag?"success":"error", message:response.message, name:response.name }); if(response.flag){ //Preview the file just uploaded this.imageUrl = "http://puco9aur6.bkt.clouddn.com/"+response.data; / / assign a value to the url, and the binding is displayed this.formData.img = response.data;//Assign the file name to the model data for form submission } }, //Execute before uploading pictures beforeAvatarUpload(file) { console.log(file); //Print file content to console const isJPG = file.type === 'image/jpeg'; //The image format is jpeg const isLt2M = file.size / 1024 / 1024 < 2; //Size less than 2M if (!isJPG) { this.$message.error('Upload package pictures can only be JPG format!'); } if (!isLt2M) { this.$message.error('Upload package picture size cannot exceed 2 MB!'); } return isJPG && isLt2M; },
3. Upload the function of each variable of the component
action: the background operation will be executed every time there is an upload behavior
<el-upload class="avatar-uploader" <!--After the pre upload callback, the upload address of the constrained file--> action="/setmeal/upload.do" <!--Auto upload--> :auto-upload="true" <!--The parameter names of the backend receiving this file must be consistent--> name="imgFile" :show-file-list="false" <!--Callback function after successful upload--> :on-success="handleAvatarSuccess" <!--Callback before upload--> :before-upload="beforeAvatarUpload"> <!--The preview effect of the picture after the picture is uploaded successfully--> <img v-if="imageUrl" :src="imageUrl" class="avatar"> //If the image is uploaded successfully, the value of the url will be assigned directly <i v-else class="el-icon-plus avatar-uploader-icon"></i>//Otherwise, it will not be displayed, and the picture set by the pair will be used instead of "+" here </el-upload>
4. Background file upload control layer
//File upload @RequestMapping("/uploadFile") public Result updoadFile(@RequestParam("imgFile") MultipartFile imgFile){ String originalFilename = imgFile.getOriginalFilename();//original filename int index = originalFilename.lastIndexOf("."); //get. Index of String suffix = originalFilename.substring(index); //Intercept according to the index jpg String fileName = UUID.randomUUID().toString() + suffix; //Generate a file name splice jpg //Save the picture to qiniu cloud try{ //Call tool class QiniuUtils.upload2Qiniu(imgFile.getBytes(),fileName); //After the file is uploaded successfully, the file name needs to be saved in redis jedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_RESOURCES,fileName); return new Result(true, MessageConstant.PIC_UPLOAD_SUCCESS,fileName); }catch (Exception e){ e.printStackTrace(); return new Result(false,MessageConstant.PIC_UPLOAD_FAIL); } }
5. Click to confirm the business layer after submitting the form
After the database is successfully inserted, it is submitted to redis in the form of stream for cache saving, mainly to save the name
//Create result object Result result = new Result(); //Insert package int meal =mealDao.insertGroup(setmeal); //Get new object id Integer id = setmeal.getId(); //Determine whether the insertion is successful //=0 indicates that the insertion failed if(meal==0){ result.setFlag(false); result.setMessage(MessageConstant.EDIT_CHECKGROUP_FAIL); return result; } //If the package is successfully inserted, the corresponding picture will be saved in redis. After confirmation, it will be submitted to redis for caching jedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_DB_RESOURCES,setmeal.getImg());//Automatically inject redispool
Storage scheme
Scheme I
nginx Reverse proxy is a simple high-performance server, which prefers static resource deployment tomcat Prefer dynamic resource deployment
Scenario: the image data that the enterprise website needs to use
Scheme II:
Open source distributed storage systems, such as Fastdfs (ALI open source), HDFS
Scenario: pictures uploaded by users during use. Avatar, circle of friends, pictures, etc.
Scheme III:
Cloud storage. Such as seven cattle cloud, baidu cloud. High cost
Scene: a large project, such as Jingdong Taobao.
authentication
Use steps:
1) Upload
1. Get local server object
2. Create a seven cow cloud object
3. Authentication (warehouse, warehouse AKey, SKey)
4. Obtain authority authentication
5. Upload (no key is specified, and the hash value is used as the file name by default)
6. Analyze upload results
2) Delete
1. Get local server object
2. Create a seven cow cloud object
3. Authentication (warehouse, warehouse AKey, SKey)
4. Specifies the file name to delete
5. Transmission instruction
6. Analytical results
Timer Quartz
Redis needs to provide cache service support during this period
Quartz definition: open source distributed timed task scheduling framework
Create a custom job Timer class and create a logical method to be executed
configuration file
1. Add timer class to spring container
2. The configuration specifies the method to be used (it must be public, otherwise it may not be called)
3. Create trigger
4. Create trigger scheduling factory
use
1. Import package (dependent on spring package)
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.2.1</version> </dependency> </dependencies>
2. Write the implementation logic of the job and use it as a war package
/** * Customize tasks and regularly clean up garbage pictures */ public class ClearImgJob { @Autowired private JedisPool jedisPool; //Clean up pictures public void clearImg(){ System.out.println("Regularly clean up garbage pictures"); Set<String> set = jedisPool.getResource().sdiff(RedisConstant.SETMEAL_PIC_RESOURCES, RedisConstant.SETMEAL_PIC_DB_RESOURCES); if(set != null){ for (String fileName : set) { System.out.println("Regularly clean up garbage pictures: " + fileName); //Delete files from qiniu ECS according to the image name QiniuUtils.deleteFileFromQiniu(fileName); //Delete picture name from redis collection jedisPool.getResource().srem(RedisConstant.SETMEAL_PIC_RESOURCES,fileName); } } } }
3. to configure
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- Register custom Job --> <bean id="jobDemo" class="com.itheima.jobs.JobDemo"></bean> <!-- register JobDetail,The function is responsible for calling the specified through reflection Job --> <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <!-- Inject target object --> <property name="targetObject" ref="jobDemo"/> <!-- Injection target method --> <property name="targetMethod" value="run"/> </bean> <!-- Register a trigger and specify the time when the task is triggered --> <bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <!-- injection JobDetail --> <property name="jobDetail" ref="jobDetail"/> <!-- Specifies the time to trigger, based on Cron expression --> <property name="cronExpression"> <value>0/10 * * * * ?</value> </property> </bean> <!-- Register a unified scheduling factory to schedule tasks through this scheduling factory --> <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <!-- Inject multiple triggers --> <property name="triggers"> <list> <ref bean="myTrigger"/> </list> </property> </bean> </beans>
Cron expression
The last of the seven positions can be separated without spaces
For example: execute 0 / 10 * * every ten seconds?
Execute 0 0 2 * * every day at 2 a.m?
0 0 / 5 3-5 * * every 5 minutes at 3-5 every morning?
name | Is it necessary | Allowable value | Special characters |
---|---|---|---|
second | yes | 0-59 | , - * / |
branch | yes | 0-59 | |
Time | yes | 0-23 | |
day | yes | 1-31 | |
month | yes | 0-11 | |
week | yes | 1-7 or SUN-SAT | |
year | no | Empty or 1970-2099 |
Apache POI upload file
It can operate all Microsoft office automation software, but it is more used to operate excel tables
Function: batch data upload / export
Introductory case
Note: 1 When reading cells, if the types are inconsistent, an error is reported
2. get data
Get rows (when getting the number of rows / cells, in order to remove the header, the row index starts from 1, and when the ordinary for loop traversal is < =, the cell index starts from 0)
Get the cell (Note: if the cell is deleted after assignment, it will also be read, and the value is "")
3. flush() forcibly flushes the cache data in memory to disk for storage
4. When compressed after excel 07, it is stored in xml file with SXSSworkbook (it does not occupy memory and does not support formulas)
Xssf workbook reads excel into memory and organizes the structure tree (occupies memory, but supports excel formula calculation)
Guide Package (only excel is supported here)
<!--poi--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> </dependency>
Read data
//Get the poi object and read the file into memory XSSFWorkbook sheets = new XSSFWorkbook("D:\\poi.xlsx"); //Get sheet page getsheetat / getsheetname //Get the first table XSSFSheet sheet = sheets.getSheetAt(0); //Loop each line for (Row row : sheet) { //Cycle through each cell of each row for (Cell cell : row) { //The data type read by conversion is string cell.setCellType(Cell.CELL_TYPE_STRING); //Get the cell information String value = cell.getStringCellValue(); //output System.out.print(value); } }
Write data
//Create poi object XSSFWorkbook workbook = new XSSFWorkbook(); //Create worksheet XSSFSheet sheet = workbook.createSheet("surface"); //Create first row XSSFRow row = sheet.createRow(0); //Create a cell for this row XSSFCell cell = row.createCell(0); //Assign a value to this row cell.setCellValue("aa11"); //Create first row XSSFCell cell_1 = row.createCell(1); //Assign a value to this row cell_1.setCellValue("bb11"); //Create output stream FileOutputStream out = new FileOutputStream("D:\\testPOI.xlsx"); //Write out excel in memory` workbook.write(out); //Refresh memory out.flush(); //Closed flow out.close(); //Close excel workbook.close();
Tool class
The method of judging the type of cell is available, and others should be used with caution
import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.web.multipart.MultipartFile; public class POIUtils { private final static String xls = "xls"; private final static String xlsx = "xlsx"; private final static String DATE_FORMAT = "yyyy/MM/dd"; /** * Read into excel file and return after parsing * @param file * @throws IOException */ //Get each row of data in the excel file public static List<String[]> readExcel(MultipartFile file) throws IOException { //audit file checkFile(file); int a = 0;//Remove duplicate lines and ignore //Get Workbook Workbook object Workbook workbook = getWorkBook(file); //Create a return object, take the values in each row as an array, and return all rows as a collection List<String[]> list = new ArrayList<String[]>(); //The getWorkBook method may return null if(workbook != null){ //Traverse several tables (table index starts from 0) for(int sheetNum = 0;sheetNum < workbook.getNumberOfSheets();sheetNum++){ //Get each table in turn Sheet sheet = workbook.getSheetAt(sheetNum); //Judge that the table is null and directly enter the next cycle if(sheet == null){ continue; } int a1= 0;//Remove duplicate lines and ignore //Gets the start line of the current sheet int firstRowNum = sheet.getFirstRowNum(); //Gets the end line of the current sheet int lastRowNum = sheet.getLastRowNum(); //Loop all rows except the first row (because there is a header and the row index starts from 1) for(int rowNum = firstRowNum+1;rowNum <= lastRowNum;rowNum++){ //Get current row Row row = sheet.getRow(rowNum); //Judge whether the behavior is null and directly enter the next cycle if(row == null){ continue; } //Get the first cell of the current row (the rule is implemented according to getLastCellNum method) int firstCellNum = row.getFirstCellNum(); //Gets the number of columns in the current row //getLastCellNum: get the last number of columns of the row (cells modified and later reset to null are also counted as one column) //getPhysicalNumberOfCells: get the number of physical columns of the row (the last column cell with value at present) //short lastCellNum = row.getLastCellNum(); //Gets how many cells the current row actually has int lastCellNum = row.getPhysicalNumberOfCells(); int a3 = 0;//Remove duplicate lines and ignore //Save the actual number of cells into String[] cells = new String[row.getPhysicalNumberOfCells()]; //Loop current row for(int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++){ Cell cell = row.getCell(cellNum);//Gets the object of the current cell cells[cellNum] = getCellValue(cell);//Determine the type of value of the object and store it in the array after conversion } list.add(cells);//Add array results to the collection } } workbook.close(); } return list; } //Verify whether the file is legal public static void checkFile(MultipartFile file) throws IOException{ //Determine whether the file exists if(null == file){ throw new FileNotFoundException("File does not exist!"); } //Get file name String fileName = file.getOriginalFilename(); //Determine whether the file is an excel file if(!fileName.endsWith(xls) && !fileName.endsWith(xlsx)){ throw new IOException(fileName + "no excel file"); } } //Judge which format it ends in and return the corresponding data type object public static Workbook getWorkBook(MultipartFile file) { //Get file name String fileName = file.getOriginalFilename(); //Create a Workbook Workbook object that represents the entire excel Workbook workbook = null; try { //Get the io stream of excel file InputStream is = file.getInputStream(); //Different Workbook implementation class objects are obtained according to different file suffixes (xls and xlsx) if(fileName.endsWith(xls)){ //2003 workbook = new HSSFWorkbook(is); }else if(fileName.endsWith(xlsx)){ //2007 workbook = new XSSFWorkbook(is); } } catch (IOException e) { e.printStackTrace(); } return workbook; } //Judge what type of cell is available and use it with caution public static String getCellValue(Cell cell){ //Judgment is null String cellValue = ""; if(cell == null){ return cellValue; } //If the current cell content is of date type, special processing is required CellStyle cellStyle = cell.getCellStyle(); String dataFormatString = cell.getCellStyle().getDataFormatString(); if(dataFormatString.equals("m/d/yy")){ //MM DD YY -- > MM DD YY cellValue = new SimpleDateFormat(DATE_FORMAT).format(cell.getDateCellValue()); return cellValue; } //Read the number as a String to avoid reading 1 to 1.0 if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){ cell.setCellType(Cell.CELL_TYPE_STRING); } //Judge the type of data switch (cell.getCellType()){ case Cell.CELL_TYPE_NUMERIC: //number cellValue = String.valueOf(cell.getNumericCellValue()); break; case Cell.CELL_TYPE_STRING: //character string cellValue = String.valueOf(cell.getStringCellValue()); break; case Cell.CELL_TYPE_BOOLEAN: //Boolean cellValue = String.valueOf(cell.getBooleanCellValue()); break; case Cell.CELL_TYPE_FORMULA: //formula cellValue = String.valueOf(cell.getCellFormula()); break; case Cell.CELL_TYPE_BLANK: //Null value cellValue = ""; break; case Cell.CELL_TYPE_ERROR: //fault cellValue = "Illegal character"; break; default: cellValue = "unknown type"; break; } return cellValue; } }
File upload vue
<!--Upload the file to the back end and directly perform logical judgment and save operation--> <!--It will be executed before uploading beforeUpload Method, for true To access the backend--> <el-upload action="/ordersetting/uploadFile" //Call the method of back-end control name="imgFile" //The front-end and back-end names must be consistent and received with @ RequestParam("imgFile") annotation :show-file-list="false" :on-success="handleSuccess" //Callback function after successful execution of action backend method :before-upload="beforeUpload" //Callback function before uploading (logical verification callback function after the user selects the picture) > <el-button type="primary">Upload file</el-button> </el-upload>
Business layer insertion
@Override //Add and upload files, batch operation public Result add(List<OrderSetting> list) { //Delete first and then insert. If there is any exception, it will directly return to batch failure try { orderSettingDao.deleteOrderSetting(list); //If the list is deleted, no error will occur and the number of rows affected is 0 orderSettingDao.insertOrderSetting(list); //insert return new Result(true,MessageConstant.IMPORT_ORDERSETTING_SUCCESS); } catch (Exception e) { e.printStackTrace(); return new Result(true,MessageConstant.IMPORT_ORDERSETTING_FAIL); } }
calendar
When the front-end parsing code is inconsistent with the fields in the database, you can use map to encapsulate and return, because there is no directly available pojo and you are lazy.
Batch add data
Reservation settings
//Built in method to convert date format this.formatDate(day.getFullYear(),day.getMonth()+1,day.getDate())
Phase II - mobile terminal development
Package cascade query
ResultMap multilevel associative query
When there is a cascading query of user-defined POJO type in the encapsulated POJO or the fields are inconsistent with pojp, it is necessary to use resultMap for mapping and encapsulation
Query help documents on the official website of mybatis: https://mybatis.org/mybatis-3/zh/index.html
Two ways
1. Pure code parsing query sql resultType circular query multiple times, affecting performance?
Parsing: each cycle requires a query, which is a simple sql connection statement
//Query package details according to package ID (package basic information, inspection group information corresponding to the package, inspection item information corresponding to the inspection group) public Setmeal findById2(int id) { Setmeal setmeal = setmealDao.findById(id); if(setmeal!=null) { // select b.* from t_setmeal_checkgroup a LEFT JOIN t_checkgroup b on a.checkgroup_id=b.id where a.setmeal_id=#{id} List<CheckGroup> checkGroups = checkGroupDao.findBySetmealId(id); for(CheckGroup group : checkGroups){ // select b.* from t_checkgroup_checkitem a LEFT JOIN t_checkitem b on a.checkitem_id=b.id where a.checkgroup_id=#{id} List<CheckItem> checkItems = checkItemDao.finByGroupId(group.getId()); group.setCheckItems(checkItems); } setmeal.setCheckGroups(checkGroups); } }
2. Cascade Association resultMap
resultMap attribute:
1) how to map pojo one by one? What are the usage scenarios of javatype and JDBC type?
2) inheritance characteristics
be careful:
1) when making the front-end page, you cannot use the table tag, because the page refresh will not be displayed uniformly until all table data are read, so you can replace it with div, li, and other tags. Avoid network jam. When the data is too large, it will be white when opening the web page
1. Page refresh starts to access data asynchronously
window.location.toString() key statement to obtain the string information of the current web address
mounted(){ //Get the string information of the web address // http://localhost:81/pages/setmeal_detail.html?id=5&name=wz var page = window.location.toString(); //According to? Perform segmentation var target = page.split("?"); //The [1] after segmentation is? Subsequent information // id=5&name=wz //Get [1] and divide it according to & to get an array var arr = target[1].split("&"); //Traversal array id=5, name=wz for(let i = 0 ;i < arr.length;i++){ //Each value should be segmented according to = to obtain array [0] ID [1] 5 let num = arr[i].split("="); //Judge whether [0] is an id. if so, the result of [1] will be returned if(num[0]=id){ //As long as you enter the page, you will send an asynchronous request to query all the information of the package and display it on the page axios.post("/setmeal/getAllInfoById?id=" + num[1]).then((response) => { if(response.data.flag){ this.setmeal = response.data.data[0]; this.imgUrl = 'http://qekirsm87.bkt.clouddn.com/' + this.setmeal.img; } }); } }
2. Call dao at the beginning of the business layer and return a package object
//Front page - query all inspection groups and inspection items @Override public Result getCheckGroupsAndCheckItems(String id) { //Call dao cascade query Setmeal setmeal = mealDao.getCheckGroupsAndCheckItemsInMeal(id); if(setmeals!=null){ return new Result(true,MessageConstant.GET_SETMEAL_LIST_SUCCESS,setmeals); } //Return results return new Result(false,MessageConstant.GET_SETMEAL_LIST_FAIL); }
3. dao of package
Analysis: 1 Enter the getCheckGroupsAndCheckItemsInMeal method to query the package information. The query results are encapsulated into the resultMap of getMeal
2. Due to the inheritance relationship, all fields can be completely encapsulated into the Setmeal object
3. Execute cascading query field checkGroups
<mapper namespace="com.wz.dao.MealDao"> <!--The result set of package query is inherited by the inspection group--> <resultMap id="baseMealResultMap" type="Setmeal"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="code" property="code"/> <result column="helpCode" property="helpCode"/> <result column="sex" property="sex"/> <result column="age" property="age"/> <result column="price" property="price"/> <result column="remark" property="remark"/> <result column="attention" property="attention"/> <result column="img" property="img"/> </resultMap> <!--Cascade query of inspection group for query results of this package--> <resultMap id="getMeal" type="SetMeal" extends="baseMealResultMap"> <!--Because it is a collection type, use collection--> <collection property="checkGroups" ofType="CheckGroup" column="id" select="com.wz.dao.CheckGroupDao.findCheckGroupAndItemByGroupId" /> </resultMap> <!--Front page,Query all check items and groups of the package--> <select id="getCheckGroupsAndCheckItemsInMeal" resultMap="getMeal"> select * from t_setmeal where id=#{id} </select> </mapper>
4. dao of inspection team
Analysis: 1 Called by the upper layer, enter in the findCheckGroupAndItemByGroupId method to start querying the inspection group information.
The query results are encapsulated into the resultMap of getGroup.
2. Due to the inheritance relationship, all fields can be completely encapsulated into the CheckGroup object
3. Execute the cascade query field checkItems. Here is a list collection, but the bottom layer will call each element separately and the next layer of sql statements will be called
<mapper namespace="com.wz.dao.CheckGroupDao"> <!--Check the mapping configuration of the group--> <resultMap id="baseGroupResultMap" type="CheckGroup"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="code" property="code"/> <result column="helpCode" property="helpCode"/> <result column="sex" property="sex"/> <result column="remark" property="remark"/> <result column="attention" property="attention"/> </resultMap> <!--Setting of cascade query check items for this check group,Here is a collection id,Will be called down in turn--> <!--So will id=5 Encapsulate one CheckItem,id=6 Encapsulate one CheckItem--> <resultMap id="getGroup" type="CheckGroup" extends="baseGroupResultMap"> <collection property="checkItems" ofType="CheckItem" column="id" select="com.wz.dao.CheckItemDao.findItemByGroupId"/> </resultMap> <!--Front end, cascading query check group--> <select id="findCheckGroupAndItemByGroupId" resultMap="getGroup"> SELECT * FROM t_checkgroup WHERE id IN (SELECT checkgroup_id FROM t_setmeal_checkgroup WHERE setmeal_id =#{id}) </select> </mapper>
5. dao of inspection items
Analysis: 1 Called by the upper layer, enter the findItemByGroupId method to start querying the information of each inspection item.
The query results are encapsulated in the CheckItem of their own resultType. Because the upper layer is a list collection, it will become an element access
2. So far, the query is completed, and the multi json nested structure of the page model is realized
setmeal:{ img:"", name:"", checkGroups:[ { name:"", code:"", checkItems:[ {name:"",code:""} ] } ] }
<!--Front end, cascading query check items--> <select id="findItemByGroupId" resultType="CheckItem"> SELECT * FROM t_checkitem WHERE id IN (SELECT checkitem_id FROM t_checkgroup_checkitem WHERE checkgroup_id=#{id}) </select>
SMS sending
Alibaba cloud SMS service ==Watch code implementation==
FreeMarker static page
Official website: http://freemarker.foofun.cn/ Query help documents
Function: make the web page respond faster. After adding, deleting and modifying, generate a static page and call it directly later
Definition: template engine developed by java language
Scenario: page static generation (the process of generating a page loaded with dynamic data into html is called static)
Such as contract template and email template
Composition: template basic template
Data required for model template
Introductory case
1. Guide Package
<!--FreeMarker--> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependencml
2. Prepare the template (the template file should end in. ftl)
<html> <head> <title>Welcome!</title> </head> <body> <h1>Welcome ${user}!</h1> <p>Our latest product: <#--I'm a comment -- > <h1>GOAWAY ${user}!</h1> <a href="${latestProduct.url}">${latestProduct.name}</a>! </body> </html>
3. Code
It is placed on disk d here. Normally, it is placed under the ftl file of the web
// Configuration cfg = new Configuration(Configuration.VERSION_2_3_22); Configuration cfg = new Configuration(Configuration.getVersion()); //Create freemaker object cfg.setDirectoryForTemplateLoading(new File("D:\\te"));//Specify template location cfg.setDefaultEncoding("UTF-8"); //Specifies the encoding of the generated template Template temp = cfg.getTemplate("ts.ftl"); //Specify the template file name //Templates can only be received in json format //Create map1 Map root = new HashMap(); root.put("user", "Blank"); //Because there is object data in the template, it is stored in the object //Mode 1: Map latest = new HashMap(); root.put("latestProduct", latest); latest.put("url", "https://www.baidu.com"); latest.put("name", "Baidu"); //Mode 2: root.put("latestProduct",new User("https://www.baidu.com "," Baidu once "); // Through a file output stream, you can write to the corresponding file. Here, the absolute path is used FileWriter out = new FileWriter("D:\\te\\test.html"); temp.process(root, out); //Generate test HTML file out.close(); //Turn off the flow, otherwise it will cause memory leakage
FreeMarker instruction
All instructions begin with #
-
assign
- Define a variable in the template page
- Use: used when debugging the template. You can define objects or strings. The priority is higher than the variable data passed in from the back end
<html> <head> <title>Welcome!</title> </head> <body> <h1>Welcome ${user}!</h1> <!-- Defining variables using instructions --> <#assign shit = "Daniel" > <h1>GOAWAY ${shit}!</h1> <#Assign info = {"mobile": "13812345678", "address": "Changping District, Beijing"} > Telephone: ${info.mobile} Address: ${info.address} <p>Our latest prodct: <#--I'm a comment -- > <a href="${latestProduct.url}">${latestProduct.name}</a>! </body> </html>
-
include
- Include other template files and enter the main template file
- Use: set the path of the template in java and start to find the template files of other paths, which are included in the main template
<html> <head> <title>Welcome!</title> </head> <body> <h1>Welcome ${user}!</h1> <#assign shit = "Daniel" > <h1>GOAWAY ${shit}!</h1> <!-- stay java The location of the file specified in the code is to find the file. And load its contents --> <#include "he.ftl"> </body> </html>
-
if
-
To judge the conditions, you can define variables in Java or assign.
-
Usage: you can use if else else else if / if to define the key of the map of the passed judgment value in java
<html> <head> <title>Welcome!</title> </head> <body> <!-- this success stay Map If there is no definition, an error will be reported --> <!-- Exist at the same time to assign Subject to --> <#if success=1> Condition 1 holds.. <#elseif success=2> Condition 2 holds.. <#else> The condition is not tenable.. </#if> </body> </html>
-
-
list
- To traverse the collection, java needs to use the list collection to store the map
- list else execute else if list is empty
- list ... as ...
HashMap<Object, Object> map = new HashMap<>(); //Templates can only be received in json format ArrayList<Map> goods = new ArrayList<>(); Map root1 = new HashMap(); root1.put("name","sa"); root1.put("price","23"); Map root2 = new HashMap(); root2.put("name","sa"); root2.put("price","23"); Map root3 = new HashMap(); root3.put("name","sa"); root3.put("price","23"); //Deposit goods.add(root1); goods.add(root2); goods.add(root3); map.put("goods",goods); // Through a file output stream, you can write to the corresponding file. Here, the absolute path is used FileWriter out = new FileWriter("D:\\te\\test.html"); temp.process(map, out);
The output format of ftl file list takes as as to traverse each
<#list goods as good> Trade name: ${good.name} Price: ${good.price}<br> </#list>
-
Built in function
- Only the date is queried in the official document of the sample here
- Use after variable when using? Function name
<html> <head> <title>Welcome!</title> </head> <body> date: Only the date part, not the time part of the day. time: Only the time part of the day, no date part. datetime: The date and time are ${openingTime?time}<br> ${openingTime?date}<br> ${openingTime?datetime}<br> //result 22:17:37 2020-8-10 2020-8-10 22:17:37 </body> </html>
Generate static pages
Timing: generate a static page when any ontology or sub item changes. The static page is generated directly from the code background without asynchronous call!
matters needing attention:
1. Specify the template storage location for the output
2. The automatic injection object in the code is FreeMarkerConfigurer
@Autowired private FreeMarkerConfigurer freeMarkerConfigurer;//Inject freemaker mapping factory
3. The access address in the template should be consistent with the address in the code. And is the absolute path of the specified disk
4. The generated master page information files are generated in the back-end code and processed logically in the front-end. For example, jump to the page, etc
5. The template shall be in End of ftl
6. Definition of each parameter
//Define in spring and inject FreeMarkerConfigurer into the code Configuration configuration = freeMarkerConfigurer.getConfiguration(); cfg.setDirectoryForTemplateLoading(new File("D:\\te"));//Specify template location cfg.setDefaultEncoding("UTF-8"); //The converted page coding format is defined in spring Template temp = cfg.getTemplate("ts.ftl"); //Which ftl template file in the specified template location is defined in java //It is defined in java and spliced with the string of external configuration file FileWriter out = new FileWriter("Output path+File name+.html"); temp.process(map data, out); //Defined in java, the incoming data is generated to the specified location
Steps:
1. Guide Package (latest version here)
<!--FreeMarker--> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependencml
2. Generate package template
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- The above three meta label*must*Put it at the top, anything else*must*Follow! --> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,user-scalable=no,minimal-ui"> <meta name="description" content=""> <meta name="author" content=""> <link rel="icon" href="../img/asset-favico.ico"> <title>make an appointment</title> <link rel="stylesheet" href="../css/page-health-order.css" /> </head> <body data-spy="scroll" data-target="#myNavbar" data-offset="150"> <div class="app" id="app"> <!-- Page header --> <div class="top-header"> <span class="f-left"><i class="icon-back" onclick="history.go(-1)"></i></span> <span class="center">Intellectual health</span> <span class="f-right"><i class="icon-more"></i></span> </div> <!-- Page content --> <div class="contentBox"> <div class="list-column1"> <ul class="list"> <li class="list-item"> <#--Loop set -- > <#list setmealList as setmeal> <#--Click the link to jump to the inspection group details page -- > <a class="link-page" href="/yemian/setmeal_detail_${setmeal.id}.html?id=${setmeal.id}"> <#--<a class="link-page" href="/yemian/setmeal_detail_${setmeal.id}.html">--> <img class="img-object f-left" src="http://qekirsm87.bkt.clouddn.com/${setmeal.img}" alt=""> <div class="item-body"> <h4 class="ellipsis item-title">${setmeal.name}</h4> <p class="ellipsis-more item-desc">${setmeal.remark}</p> <p class="item-keywords"> <span> <#if setmeal.sex == '0'> Unlimited gender <#else> <#if setmeal.sex == '1'> male <#else> female </#if> </#if> </span> <span>${setmeal.age}</span> </p> </div> </a> </#list> </li> </ul> </div> </div> </div> <script> var vue = new Vue({ el:'#app', data:{ setmealList:[] } }); </body>
3. Generate inspection group template
1.json format return (recommended)
The fastjson dependency package used here. Not recommended
Modified to freemaker syntax, vue is automatically bound to the page in both directions, and the memory consumption is small!!
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- The above three meta label*must*Put it at the top, anything else*must*Follow! --> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,user-scalable=no,minimal-ui"> <meta name="description" content=""> <meta name="author" content=""> <link rel="icon" href="../img/asset-favico.ico"> <title>Appointment details</title> <link rel="stylesheet" href="../css/page-health-orderDetail.css" /> <script src="../plugins/vue/vue.js"></script> <script src="../plugins/vue/axios-0.18.0.js"></script> <script src="../plugins/healthmobile.js"></script> <script> var id = getUrlParam("id"); </script> </head> <body data-spy="scroll" data-target="#myNavbar" data-offset="150"> <div id="app" class="app"> <!-- Page header --> <div class="top-header"> <span class="f-left"><i class="icon-back" onclick="history.go(-1)"></i></span> <span class="center">Intellectual health</span> <span class="f-right"><i class="icon-more"></i></span> </div> <!-- Page content --> <div class="contentBox"> <div class="card"> <div class="project-img"> <img :src="imgUrl" width="100%" height="100%" /> </div> <div class="project-text"> <h4 class="tit">{{setmeal.name}}</h4> <p class="subtit">{{setmeal.remark}}</p> <p class="keywords"> <span>{{setmeal.sex == '0' ? 'Unlimited gender' : setmeal.sex == '1' ? 'male':'female'}}</span> <span>{{setmeal.age}}</span> </p> </div> <!--<div class="project-know"> <a href="orderNotice.html" class="link-page"> <i class="icon-ask-circle"><span class="path1"></span><span class="path2"></span></i> <span class="word">Booking instructions</span> <span class="arrow"><i class="icon-rit-arrow"></i></span> </a> </div>--> </div> <div class="table-listbox"> <div class="box-title"> <i class="icon-zhen"><span class="path1"></span><span class="path2"></span></i> <span>Package details</span> </div> <div class="box-table"> <div class="table-title"> <div class="tit-item flex2">entry name</div> <div class="tit-item flex3">Project content</div> <div class="tit-item flex3">Project interpretation</div> </div> <div class="table-content"> <ul class="table-list"> <li class="table-item" v-for="checkgroup in setmeal.checkGroups"> <div class="item flex2">{{checkgroup.name}}</div> <div class="item flex3"> <label v-for="checkitem in checkgroup.checkItems"> {{checkitem.name}} </label> </div> <div class="item flex3">{{checkgroup.remark}}</div> </li> </ul> </div> <div class="box-button"> <a @click="toOrderInfo()" class="order-btn">Make an appointment now</a> </div> </div> </div> </div> </div> <script> var vue = new Vue({ el:'#app', data:{ imgUrl:null,//Picture link corresponding to the package //When using json format to send back, you only need to modify it to freemaker syntax here. vue is automatically bound to the page in both directions, and the memory consumption is small!! setmeal:${key} }, methods:{ toOrderInfo(){ window.location.href = "/pages/orderInfo.html?id=" + id; } }, }); </script> </body>
2. Regular return
(placeholders use freemaker syntax)
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- The above three meta label*must*Put it at the top, anything else*must*Follow! --> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,user-scalable=no,minimal-ui"> <meta name="description" content=""> <meta name="author" content=""> <link rel="icon" href="../img/asset-favico.ico"> <title>Appointment details</title> <link rel="stylesheet" href="../css/page-health-orderDetail.css" /> <script src="../plugins/vue/vue.js"></script> <script src="../plugins/vue/axios-0.18.0.js"></script> <script src="../plugins/healthmobile.js"></script> <script> var id = getUrlParam("id"); </script> </head> <body data-spy="scroll" data-target="#myNavbar" data-offset="150"> <div id="app" class="app"> <!-- Page header --> <div class="top-header"> <span class="f-left"><i class="icon-back" onclick="history.go(-1)"></i></span> <span class="center">Intellectual health</span> <span class="f-right"><i class="icon-more"></i></span> </div> <!-- Page content --> <div class="contentBox"> <div class="card"> <div class="project-img"> <img :src="imgUrl" width="100%" height="100%" /> </div> <div class="project-text"> <h4 class="tit">${setmeal.name}</h4> <p class="subtit">${setmeal.remark}</p> <p class="keywords"> <span> <#if setmeal.sex == '0'> Unlimited gender <#else> <#if setmeal.sex == '1'> male <#else> female </#if> </#if> </span> <span>${setmeal.age}</span> </p> </div> </div> <div class="table-listbox"> <div class="box-title"> <i class="icon-zhen"><span class="path1"></span><span class="path2"></span></i> <span>Package details</span> </div> <div class="box-table"> <div class="table-title"> <div class="tit-item flex2">entry name</div> <div class="tit-item flex3">Project content</div> <div class="tit-item flex3">Project interpretation</div> </div> <div class="table-content"> <ul class="table-list"> <#list setmeal.checkGroups as checkgroup> <li class="table-item"> <div class="item flex2">${checkgroup.name}</div> <div class="item flex3"> <#list checkgroup.checkItems as checkitem> <label> ${checkitem.name} </label> </#list> </div> <div class="item flex3">${checkgroup.remark}</div> </li> </#list> </ul> </div> <div class="box-button"> <a @click="toOrderInfo()" class="order-btn">Make an appointment now</a> </div> </div> </div> </div> </div> <script> var vue = new Vue({ el:'#app', data:{ imgUrl:null,//Picture link corresponding to the package setmeal:{} }, methods:{ toOrderInfo(){ window.location.href = "/pages/orderInfo.html?id=" + id; } } }); </script> </body>
4. Tools
Function: after the addition, deletion and modification operations are completed, the method is directly executed, and the internal method is queried to generate a template. The front end automatically accesses the template.
//Generate template method public void makeTemplate(String templateFileName, String pageName, Map data) throws Exception { //Get objects through factory Configuration configuration = freeMarkerConfigurer.getConfiguration(); //Specify template Template template = configuration.getTemplate(templateFileName); //Create output stream FileWriter fileWriter = new FileWriter(new File(outputpath+"/"+pageName)); //Output template template.process(data,fileWriter); //Closed flow fileWriter.close(); } -----------------------------Detailed page--------------------------------------------------------------------- -----------------------------Detailed page--------------------------------------------------------------------- -----------------------------Detailed page--------------------------------------------------------------------- //Method of generating detailed page public void makeStaticDetailPage(List<Setmeal> list) throws Exception { //Define template name // String templateName = "setmeal_detail.ftl"; String templateName = "setmeal_detailForSmall.ftl"; //Template returned using map //Cyclic set for(Setmeal setmeal : list){ //Define the generated file name, and the end of the file ends according to the package id. It is convenient for the front-end to find out when using the cycle String detailPageName = "setmeal_detail_"+String.valueOf(setmeal.getId()+".html"); //Cascade query all subsets to obtain results List<Setmeal> s = mealDao.getCheckGroupsAndCheckItemsInMeal(String.valueOf(setmeal.getId())); //Get the queried package object Setmeal smeal = s.get(0); //Create map HashMap<String, String> map = new HashMap<>(); String s1 = JSON.toJSONString(smeal); //Save to collection // map.put("setmeal",smeal); map.put("key",s1); //When using the template of map. Return json format //Call basic template method to generate static page makeTemplate(templateName,detailPageName,map); } -----------------------------Package page--------------------------------------------------------------------- -----------------------------Package page--------------------------------------------------------------------- -----------------------------Package page--------------------------------------------------------------------- //Method of generating package page //Generate the package page, throw up the exception, and the one who calls will handle it public void makeStaticPage(List<Setmeal> list) throws Exception { //Define data HashMap<String, List<Setmeal>> map = new HashMap<>(); //Save to map map.put("setmealList",list); //Define template name String templateName = "m.ftl"; //Define the generated file name String mealPageName = "mealPage.html"; //Call the basic template method to generate a web page and output it to the specified location makeTemplate(templateName,mealPageName,map); }
5. Configuration file
1. Configure freemarkerConfig in the spring container in the business layer
<!--to configure freemarker Template object--> <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <!--Specify the directory where the template file is located, which cannot be accessed externally--> <property name="templateLoaderPath" value="/WEB-INF/ftl/" /> <!--Specify character set--> <property name="defaultEncoding" value="UTF-8" /> </bean>
2. Create external file for address
outputPath=F:/ideaProject/project/projectHEALTH/mobile/src/main/webapp/yemian //Absolute path of webapp on disk in the project
6. Modify the initial access interface
In the index, modify the first jump position as the template page
Confirm appointment
datepicker date control Android
The back-end of ID card verification is the ID card obtained by the server connected to the Public Security Bureau? The ID card has a set of verification rules
Why can't the pre submission verification here be handed over to vue? The number of verification backend visitors is small
How can the front-end page verify the regularity on the basis of losing focus? async-validator
Provide a general query condition to return the list set and template
<!--Dynamic condition query--> <select id="findByCondition" parameterType="com.itheima.pojo.Order" resultMap="baseResultMap"> select * from t_order <where> <if test="id != null"> and id = #{id} </if> <if test="memberId != null"> and member_id = #{memberId} </if> <if test="orderDate != null"> and orderDate = #{orderDate} </if> <if test="orderType != null"> and orderType = #{orderType} </if> <if test="orderStatus != null"> and orderStatus = #{orderStatus} </if> <if test="setmealId != null"> and setmeal_id = #{setmealId} </if> </where> </select>
Authority control (RBAC)
Why should the cookie be set to / so that not all paths will carry the cookie? General operation all pages need to be verified
The interception rule / * * intercepts all requests, which is unique to the / * security framework previously used
Using annotations, after authentication, this can access other methods. Is it defined in memory using the value string
Configure the form and loginout tags. What if there are other customized pages to be released?
<security:http security="none" pattern="/pages/a.html"></security:http>
How to jump to the service page from spring
<security:authentication-provider user-service-ref="logical">
The spring security framework supports the following functions:
Login: automatically generate login URL for entering password account.
Authentication: the bottom layer of the framework automatically connects with the results of the specified method through the secret code website.
Authentication: judge the permission according to the given method
Exit: the bottom layer of the framework automatically logs off all permission functions through the password URL
site: spring.io keyword query according to the keyword of the website
matters needing attention
1.access and exception should be consistent
2. When configuring users, {noop} of password indicates whether to configure the plaintext
3. Using the form tag, the form submission must be post, otherwise 404
4. If you encounter ifram nested web pages, it is considered unsafe. You need to configure the security: header tag in the http tag
Project definition: war package, not inheriting the parent project
In the web
/Do not intercept JSPS
/No interception*
*. do intercept only Do end request
step
pom.xml
1. Import dependent packages
In general, we need to rely on spring, which is not given here
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> </dependency>
web.xml
2. Configure delegatingFilterproxy delegation filter
delegatingFilterproxy class function: integrate the tripartite framework, including shrio
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <filter> <!-- DelegatingFilterProxy Used to integrate third-party frameworks integration Spring Security The name of the filter must be springSecurityFilterChain, Otherwise, it will be thrown NoSuchBeanDefinitionException abnormal --> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- Specify the loaded configuration file through parameters contextConfigLocation load --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
spring.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context" xmlns:security="http://www.springframework.org/schema/security" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd "> <!--Sweep bag--> <context:component-scan base-package="com.wz"/> <!--Release static page--> <mvc:default-servlet-handler/> <!--scanning spring Annotation of framework--> <mvc:annotation-driven/> <!-- Configure layer 2 interceptor --> <!--1.Configure addresses that can be accessed directly--> <!--<security:http security="none" pattern="/pages/a.html"></security:http>--> <!--2.Configure the address to be intercepted--> <!--Due to permission verification, if not, it will automatically jump to the framework login page--> <security:http auto-config="true" use-expressions="true"> <!-- This role is required to access the following web pages --> <security:intercept-url pattern="/user/**" access="hasRole('ROLE_ADMIN')" /> <security:intercept-url pattern="/TT/**" access="hasRole('ROLE_GOOD')" /> <security:intercept-url pattern="/pages/**" access="isAuthenticated()" /> <!--Anonymous Access --> <!--<security:intercept-url pattern="/pages/**" access="isAnonymous()" />--> <!--Custom login page--> <!--Because the custom page is set, you need to use the interceptor caller to authorize--> <security:form-login login-page="/login.html" username-parameter="account" password-parameter="password" login-processing-url="/hhhh" default-target-url="/index.html" authentication-failure-url="/login.html"></security:form-login> <!--Turn off the filter of the custom form, and all requests will be intercepted--> <security:csrf disabled="true"></security:csrf> <!--Log out and log out all permission information--> <security:logout logout-url="/logout" logout-success-url="/login.html" invalidate-session="true" /> </security:http> <!--Configure layer 3 interceptors, which are mainly used for logical control and allocation of permissions--> <security:authentication-manager> <!-- Define interceptor caller --> <!--<security:authentication-provider user-service-ref="logical">--> <security:authentication-provider > <!-- Configure a specific user data write dead, as long as it meets name,pwd Just give me permission --> <security:user-service> <!--{noop}Indicates that plaintext is used--> <security:user name="admin1" password="{noop}123" authorities="ROLE_ADMIN"/> </security:user-service> <!--Specify the object to be encrypted with password, and the underlying layer will encrypt it by itself--> <!--Carry out password verification in the password address. If the password is correct, give permission--> <!--<security:password-encoder ref="passwordEncoder"></security:password-encoder>--> </security:authentication-provider> </security:authentication-manager> <!--Enable annotation mode permission control--> <security:global-method-security pre-post-annotations="enabled" /> <!-- definition bean,For logical allocation --> <bean id="logical" class="com.wz.LogicalService"></bean> <!--Configure password encryption object--> <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" /> <!--<dubbo:application name="dubbo_controller" />--> <!--<!–Specify service registry address–>--> <!--<dubbo:registry address="zookeeper://localhost:2181"/>--> <!--<!–Batch scan–>--> <!--<dubbo:annotation package="com.wz" />--> </beans>
Rectification of Project Authority
The annotation here can only use one permission. How to write if you want multiple permissions? json cannot use and to connect multiple permissions
1. Jointly query all permissions to reduce the performance consumption of the database. Otherwise, the more permissions and roles, the more queries to access the database. If you combine queries, you can query all of them only once
Optimization scheme:
1. The mian page is optimized to display the user's name
2. The corresponding permission operation button is displayed. If there is a deletion, it will be displayed
3. If the deletion fails, a prompt will be given, and the permission is insufficient (choose one of 2 / 3)
File export
Upgrade self-study poi: easypoi toolkit, easy excel, Alibaba's poi performance optimization project
Create one object at a time?
Mode 1:
Export a template directly
window.location.href = '/report/BusinessReport.xlsx'; //Export template files stored in a region of the server
Mode 2:
ajax is not used here, because if it is used, the stream needs to be encapsulated as sjon return
Access the background, generate data, and then export it by stream
package com.wz.analysis; import com.alibaba.dubbo.config.annotation.Reference; import com.interfaces.Analysis; import com.wz.result.MessageConstant; import com.wz.result.Result; import org.apache.poi.xssf.usermodel.*; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.OutputStream; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController @RequestMapping("/report") public class MemberAnalysis { @Reference private Analysis analysis; //Call the method to get the new number of people per month in the past year @RequestMapping("/showMemberReport") public Map showMemberReport(){ Map map = analysis.checkMemberCountByMonths(); return map; } //Call the method to get the new number of people per month in the past year @RequestMapping("/showMealReport") public Map showMealReport(){ //Call the method to get the reservation quantity of each package Map map = analysis.checkMealReservation(); return map; } //Call method to get report data @RequestMapping("/showReport") public Result showReport(){ try{ Map<String,Object> data = analysis.checkReportInfo(); return new Result(true,MessageConstant.GET_BUSINESS_REPORT_SUCCESS,data); }catch (Exception e){ return new Result(false,MessageConstant.GET_BUSINESS_REPORT_FAIL); } } //export report @RequestMapping("/exportBusinessReport") public Result exportBusinessReport(HttpServletRequest request, HttpServletResponse response) throws Exception { try { //Read in template file String filePath = request.getSession().getServletContext().getRealPath("template") + File.separator + "report_template.xlsx"; //Get file workbook object XSSFWorkbook excel = new XSSFWorkbook(new FileInputStream(new File(filePath))); // //get data Map<String, Object> result = analysis.checkReportInfo(); //Take out the returned result data and prepare to write the report data into Excel file String reportDate = (String) result.get("reportDate"); Integer todayNewMember = (Integer) result.get("todayNewMember"); Integer totalMember = (Integer) result.get("totalMember"); Integer thisWeekNewMember = (Integer) result.get("thisWeekNewMember"); Integer thisMonthNewMember = (Integer) result.get("thisMonthNewMember"); Integer todayOrderNumber = (Integer) result.get("todayOrderNumber"); Integer thisWeekOrderNumber = (Integer) result.get("thisWeekOrderNumber"); Integer thisMonthOrderNumber = (Integer) result.get("thisMonthOrderNumber"); Integer todayVisitsNumber = (Integer) result.get("todayVisitsNumber"); Integer thisWeekVisitsNumber = (Integer) result.get("thisWeekVisitsNumber"); Integer thisMonthVisitsNumber = (Integer) result.get("thisMonthVisitsNumber"); List<Map> hotSetmeal = (List<Map>) result.get("hotSetmeal"); // XSSFSheet sheet = excel.getSheetAt(0); // Get how many rows and columns are public int rowNum = sheet.getLastRowNum(); //Get all rows for (int i = 0; i <=rowNum ; i++) { XSSFRow row = sheet.getRow(i); //Get single line object if(row!=null){ int colNum = row.getLastCellNum(); //Gets the last cell of the row. Contains used cells for (int j = 0; j < colNum; j++) { XSSFCell cell = row.getCell(j); //Get each cell object if(cell!=null){ XSSFCellStyle cellStyle = cell.getCellStyle(); //Get style object // The red background is FFFF0000 // The green background is FF00B050 if(cellStyle.getFillForegroundColorColor()!=null) { //Judge whether there is color String color = cellStyle.getFillForegroundColorColor().getARGBHex(); //Get color number System.out.println(cell.getStringCellValue()+"\t:"+color+"\t"+result.get(cell.getStringCellValue())); if("FFFF0000".equals(color)||"FFFFFF00".equals(color)){ //Judge whether it is the specified color. The color here is bright red and green String [] name = cell.getStringCellValue().split(":"); //Split the cells to determine whether the hot plate has been reached cellStyle.setFillForegroundColor(new XSSFColor(Color.YELLOW)); //Fill new style if(name.length==2) {//Judge whether the split result really reaches the hot plate Map map = (Map) result.get(name[0]); //Sethotkey here, sethotkey here cell.setCellValue("" + map.get(name[1])); //value }else{ //The value of each cell to be filled in the template is the key of the result query result cell.setCellValue("" + result.get(cell.getStringCellValue())); } } } } } } } //Use the output stream to download the form, and download it as a client based on the browser OutputStream out = response.getOutputStream(); response.setContentType("application/vnd.ms-excel");//Represents the Excel file type response.setHeader("content-Disposition", "attachment;filename=report.xlsx");//Specify download as attachment excel.write(out); out.flush(); out.close(); // excel.close(); return null; }catch (Exception e){ e.printStackTrace(); return new Result(false,MessageConstant.GET_SETMEAL_COUNT_REPORT_FAIL); } } }
JasperReport simulation Designer
Note: 1 When using the form, the data source is specified, so the data can be displayed
However, if it is executed in the program, there is no way to close it. There will be problems, so don't
2. When generating the border, in order to have no gap. To zoom out each area, the lower line of the previous area
3. If Chinese cannot be displayed normally, use Chinese Song typeface and add pudding file at the same level as jrxml template
Try not to use the fields function to make reports in the future?
Output stream ateBytes. tostring
XX.class. -->
getResource ("") takes the files under the same package
getResource ("/") takes the file under the class file
getClassLoader.getResource(" ")
getClassLoader.getResource(" /")
Introductory case
@Test public void show() throws Exception { //Define template location String jrxmlPath ="F:\\ideaProject\\project\\projectHEALTH\\controller\\src\\main\\resources\\demo.jrxml"; //Define virtual output location and name String jasperPath ="F:\\ideaProject\\project\\projectHEALTH\\controller\\src\\main\\resources\\demo.jasper"; JasperCompileManager.compileReportToFile(jrxmlPath,jasperPath); //Compile template //Define header data Map paramters = new HashMap(); paramters.put("reportDate","2019-10-10"); paramters.put("company","itcast"); //Define template master data List<Map> list = new ArrayList(); HashMap<Object, Object> map1 = new HashMap<>(); map1.put("name","xiaoming"); map1.put("address","beijing"); map1.put("email","xiaoming@itcast.cn"); Map map2 = new HashMap(); map2.put("name","xiaoli"); map2.put("address","nanjing"); map2.put("email","xiaoli@itcast.cn"); list.add(map1); list.add(map2); //Fill in the data and use the javaBean class JasperPrint jasperPrint =JasperFillManager.fillReport(jasperPath,paramters,new JRBeanCollectionDataSource(list)); //Define output file location String pdfPath = "D:\\test.pdf"; JasperExportManager.exportReportToPdfFile(jasperPrint,pdfPath); //export } }
Color.YELLOW)); // Fill new style
if(name.length==2) {/ / judge whether the split result really reaches the popular plate
Map map = (Map) result. get(name[0]); // Sethotkey here, sethotkey here
cell.setCellValue("" + map.get(name[1])); //value
}else{
//The value of each cell to be filled in the template is the key of the result query result
cell.setCellValue("" + result.get(cell.getStringCellValue()));
}
}
}
}
}
}
}
//Use the output stream to download the form, and download it as a client based on the browser OutputStream out = response.getOutputStream(); response.setContentType("application/vnd.ms-excel");//Represents the Excel file type response.setHeader("content-Disposition", "attachment;filename=report.xlsx");//Specify download as attachment excel.write(out); out.flush(); out.close();
// excel.close();
return null;
}catch (Exception e){
e.printStackTrace();
return new Result(false,MessageConstant.GET_SETMEAL_COUNT_REPORT_FAIL);
}
}
}
## JasperReport simulation Designer Note: 1.When using the form, the data source is specified, so the data can be displayed However, if it is executed in the program, there is no way to close it. There will be problems, so don't 2.When generating the border, in order to have no gap. To zoom out each area, the lower line of the previous area 3.If Chinese cannot be displayed normally, use Chinese Song typeface and add pudding files and jrxml Template sibling ==Try not to use it in the future feilds Function: create report?== Output stream ateBytes . tostring XX.class. --> getResource(" ") Take the same package and put down the documents getResource("/ ")take class File under file getClassLoader.getResource(" ") getClassLoader.getResource(" /") Introductory case ```java @Test public void show() throws Exception { //Define template location String jrxmlPath ="F:\\ideaProject\\project\\projectHEALTH\\controller\\src\\main\\resources\\demo.jrxml"; //Define virtual output location and name String jasperPath ="F:\\ideaProject\\project\\projectHEALTH\\controller\\src\\main\\resources\\demo.jasper"; JasperCompileManager.compileReportToFile(jrxmlPath,jasperPath); //Compile template //Define header data Map paramters = new HashMap(); paramters.put("reportDate","2019-10-10"); paramters.put("company","itcast"); //Define template master data List<Map> list = new ArrayList(); HashMap<Object, Object> map1 = new HashMap<>(); map1.put("name","xiaoming"); map1.put("address","beijing"); map1.put("email","xiaoming@itcast.cn"); Map map2 = new HashMap(); map2.put("name","xiaoli"); map2.put("address","nanjing"); map2.put("email","xiaoli@itcast.cn"); list.add(map1); list.add(map2); //Fill in the data and use the javaBean class JasperPrint jasperPrint =JasperFillManager.fillReport(jasperPath,paramters,new JRBeanCollectionDataSource(list)); //Define output file location String pdfPath = "D:\\test.pdf"; JasperExportManager.exportReportToPdfFile(jasperPrint,pdfPath); //export } }