This series is divided into four parts:
  • Site construction tetralogy of back-end interface (SpringBoot+ online)
  • Python Data Crawler (Selenium)
  • Site construction tetralogy before the display (React+ online)
  • Mobile Terminal part of tetralogy of website construction (Android+ online)

Zero, preface,

This series is to summarize the knowledge at hand and pay tribute to my 2018

The focus of this article is to build a backend URL interface service and run it on the server. The technical points summarized in this article are SpringBoot, MyBaits integration, mysql simple operation, ResetFul interface, file upload, cross-domain processing


I. Initial setup of SpringBoot

1. New SpringBoot project in Idea (subcontract as follows) :

Press any key projects, new here don’t talk nonsense, novice please go to: [experience] at the beginning of the SpringBoot – 01 – (www.jianshu.com/p/74f0d9573…

)


Add dependencies to POm. XML:
<dependencies> <! </groupId> </artifactId> </artifactId> </dependency> <! <groupId>org.mybatis. Spring. Boot </groupId> < artifactId > mybatis - spring - the boot - starter < / artifactId > < version > 1.3.2 < / version > < / dependency > <! </groupId> </artifactId> </artifactId> </artifactId> </artifactId> </artifactId> <version>RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>Copy the code

3. Configure application.properties(or application.yml, I prefer the latter)

The database name is mycode, the username is username: XXXX, and the password is password: XXXX

spring: datasource: url: jdbc:mysql://localhost:3306/mycode? useSSL=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&URIEncoding="UTF -8" username: root password: **** driver-class-name: com.mysql.jdbc. driver mapper-locations: classpath:mapper/*.xmlCopy the code

Mark stepped in two pits:

'&serverTimezone=Asia/Shanghai' can be fixed. '&URIEncoding="UTF-8"' was added to the database connection parameter during the > configurationCopy the code

A simple summary of MySQL

1, build database build table
1). Determine the monomer you want
{"id":"1" "type": "drawing related ", "name": "Everything You Know and Don't Know about Canvas on Android ", "localPath":"I:\Java\Android\Unit\C\app\src\main\java\com\toly1994\c\view\CanvasView.java", "jianshuUrl":"https://www.jianshu.com/p/4bc05f646bfe", "juejinUrl":"https://juejin.cn/post/6844903705930629128", ImgUrl :" Domain: Port /Android /Android Everything you know and don't know about Canvas. PNG ", "createTime":"2018-11-05"}Copy the code

2). Create databasemycodeAnd the tableandroid
// CREATE DATABASE mycode; USE mycode; CREATE TABLE android (ID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, type VARCHAR(8) NOT NULL, name VARCHAR(32) NOT NULL, localPath VARCHAR(120) NOT NULL, jianshuUrl VARCHAR(120) NOT NULL, juejinUrl VARCHAR(120) NOT NULL, imgUrl VARCHAR(120) NOT NULL, createTime DATE NOT NULL );Copy the code


3). To summarize the federated query, create a tabletype
CREATE TABLE type(
   id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
   type_idx  VARCHAR(4)   NOT NULL,
   type  VARCHAR(48)  NOT NULL
 );
Copy the code
4). Insert type data:
INSERT INTO the type (type_idx, type) VALUES (' terms', 'four components), (' C', 'drawing related), (' D', 'custom controls), (' F', 'fragments'), (" G ", 'open source project), (' V', 'native View), (' MD', 'material design), (the' L ', 'the underlying core'), (the 'M', 'multimedia related), (' N', 'network related), (' O', 'tripartite framework), (' P', 'mobile phone equipment related'), ('S', 'data store read correlation '), ('T',' Clutter small technology ');Copy the code


2. A brief review of MySQL statements
--> Insert data: Insert into android (type, name, localPath, jianshuUrl, juejinUrl, imgUrl, createTime) values (XX, XX, XX, XX, XX, XX, XX) - > update data:  UPDATE android SET type=XX,name=XX,localPath=XX,jianshuUrl=XX,juejinUrl=XX,imgUrl=XX,createTime=XX WHERE id=XX +INNER JOIN <select ID ="findALL" resultType="toly1994.com.android_project.bean.Note"> SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,createTime FROM android AS a INNER JOIN type AS t ON a.type = t.type_idx; < / select > -- > according to the id of the select Anderson d, name, t.t ype, localPath, jianshuUrl, juejinUrl, imgUrl, createTime FROM android AS a INNER JOIN type AS T ON a.type = t.type_idx WHERE a.id=XX --> SELECT by type a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,createTime FROM android AS a INNER JOIN type AS t ON a.type = t.type_idx WHERE a.type=XX; -- > according to the query name part of the character SELECT Anderson d, name, t.t ype, localPath, jianshuUrl, juejinUrl, imgUrl, createTime FROM android AS a INNER JOIN type AS t ON a.type = t.type_idx WHERE name like '%XX%'; --> DELETE FROM android WHERE id=#{id}Copy the code

Iii. Writing process + Insertion test:

1. File introduction

1. AndroidProjectApplication. Java startup files, Application.yml configuration file 3.note. XML Operate the database by SQL statement to map entity classes and return them to dao 4.Notedao. Java Database operation interface 5.Noteservice Note. Java entity class, used to undertake the data in the database 7.NoteControllerCopy the code

Let’s insert the data to demonstrate the operation process


Create an entity class:toly1994.com.android_project.bean.Note.java
public class Note {
    private int id;//id
    private String type;//类型
    private String name;//名称
    private String localPath;//路径
    private String jianshuUrl;//简书地址
    private String juejinUrl;//掘金地址
    private String imgUrl;//掘金地址
    private String createTime;//创建时间
    //构造方法,get、set、toString略
}
Copy the code

3. The mapping XML: mapper/Note. XML

According to the specification, just write the SQL statement in the appropriate place

Where #{type} represents the parameter passed in to the dao method

<? The XML version = "1.0" encoding = "utf-8"? > <! DOCTYPE mapper PUBLIC "- / / mybatis.org//DTD mapper / 3.0 / EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <! <mapper namespace="toly1994.com.android_project.dao.NoteDao"> <! -- Pit point 3: Id for the corresponding method of dao - > < insert id = "insert" > insert into android (type, name, localPath, jianshuUrl juejinUrl, imgUrl, createTime) values (#{type},#{name},#{localPath},#{jianshuUrl},#{juejinUrl},#{imgUrl},#{createTime}) </insert> </mapper>Copy the code

4. Database operations: toly1994.com.android_project.dao.NoteDao
/** * Author: Zhang Feng jiete Lie * Time: 2018/11/19 0019:13:27 * Email: [email protected] * Description: @param ("name") @param ("name") @param ("name") @param ("name"); Int insert(@param ("type") String type, @param ("name") String name, @param ("localPath") String localPath, @param ("localPath") String localPath, @Param("jianshuUrl") String jianshuUrl, @Param("juejinUrl") String juejinUrl, @Param("imgUrl") String imgUrl, @Param("createTime") String createTime); }Copy the code

5. The business layer: toly1994.com.android_project.service.NoteService
/** * Author: Zhang Feng jiete Lie * Time: 2018/11/19 0019:13:48 * Email: [email protected] * Description: */ @service public class NoteService {@autowired private NoteDao mNoteDao; @Transactional public String insertNote(Note note) { mNoteDao.insert(note.getType(), note.getName(), note.getLocalPath(), note.getJianshuUrl(), note.getJuejinUrl(), note.getImgUrl(), note.getCreateTime()); return "OK"; }}Copy the code

6. Control layer: toly1994.com.android_project.controller.NoteController
/** * Author: Zhang Feng jiete Lie * Time: 2018/11/19 0019:13:34 * Email: [email protected] * Description: */ @restController public class NoteController {@autowired private NoteService mNoteService; @getMapping ("/test/insert") public String insert() {Note Note = new Note("C", "Android knows and doesn't know about Canvas ", "I:\\Java\\Android\\Unit\\C\\app\\src\\main\\java\\com\\toly1994\\c\\view\\CanvasView.java" , "https://www.jianshu.com/p/4bc05f646bfe", "https://juejin.cn/post/6844903705930629128", "Http://localhost:8080/android/Android you know and don't know about Canvas. PNG", "null"); mNoteService.insertNote(note); return "ok"; }}Copy the code

7. Startup class: pay attention to pit point, startup class, and sweep the package
@mapPerscan (basePackages = {"toly1994.com.android_project.dao"}) public class AndroidProjectApplication { public static void main(String[] args) { SpringApplication.run(AndroidProjectApplication.class, args); }}Copy the code

By accessing the interface in the browser, you can insert data into the database.


4. Implement RESTFUL APIS (simple CRUD)

1. Add data to POST:http://domain name: port/API /android/note

RESTFUL interfaces: / API/Android /XXX

Modify the controller: NoteController to change the insert method to POST and return the insert information (json format) to the visitor after the insert.

/** * Author: Zhang Feng jiete Lie * Time: 2018/11/19 0019:13:34 * Email: [email protected] * Description: */ @restController @RequestMapping(value = "/ API /android") public class NoteController {@autowired private NoteService mNoteService; @PostMapping(value = "/note") public Note addOne(@ModelAttribute Note note) { mNoteService.insertNote(note); return note; }}Copy the code


2.PUT modify data:http://192.168.43.60:8089/api/android/note/ [id]
1).mapper/ note.xml: add SQL statement
<update id="updateById">
    UPDATE android
    SET type=#{type},name=#{name},localPath=#{localPath},jianshuUrl=#{jianshuUrl},juejinUrl=#{juejinUrl},imgUrl=#{imgUrl}
    WHERE id=#{id}
</update>
Copy the code
2).NoteDao: Add method interface
/** * Modify a record by id ** @param id * @return */ void updateById(@param ("id") int ID, @param ("type") String type, @Param("name") String name, @Param("localPath") String localPath, @Param("jianshuUrl") String jianshuUrl, @Param("juejinUrl") String juejinUrl, @Param("imgUrl") String imgUrl, @Param("createTime") String createTime);Copy the code
3).NoteService: Add the Service layer method
@Transactional
public Note updateNote(int id, Note note) {
    mNoteDao.updateById(id,
            note.getType(),
            note.getName(),
            note.getLocalPath(),
            note.getJianshuUrl(),
            note.getJuejinUrl(),
            note.getImgUrl(),
            note.getCreateTime());
    return note;
}
Copy the code
4).NoteController: Add url access interface
@PutMapping(value = "/note/{id}")
public Note updateById(@PathVariable("id") Integer id, @ModelAttribute Note note) {
    mNoteService.updateNote(id,note);
    return note;
}
Copy the code


3. Query data:

After the above several, should be familiar with the writing:

Add methods to dao, then write SQL, and then transition dao to Controller using Service

//DAO /** * query all * @return */ List<Note> findALL(); Select id="findALL" resultType="toly1994.com.android_project.bean.Note"> select *FROM android </select> //Service public List<Note> findAll() { return mNoteDao.findALL(); } //Controller @GetMapping(value = "/note") public List<Note> findAll() { return mNoteService.findAll(); }Copy the code


4. Query a single field (take the ID field as an example. Other fields are similar)
//DAO /** * @return */ Note findById(@param ("id") int id); <select id="findById" resultType="toly1994.com.android_project.bean.Note"> select *FROM Android WHERE id=#{id} </select> //Service public Note findById(int id){ return mNoteDao.findById(id); } //Controller @GetMapping(value = "/note/{id}") public Note findById(@PathVariable("id") Integer id) { return mNoteService.findById(id); }Copy the code


5. Delete a single data (take the ID field as an example, other fields are similar)
//DAO /** * delete * @param id */ void deleteById(@param ("id") int id); <delete id="deleteById"> delete FROM android WHERE id=#{id} </delete> Service @transactional public int deleteById(int id){ mNoteDao.deleteById(id); return id; } //Controller @DeleteMapping(value = "/note/{id}") public int deleteById(@PathVariable("id") Integer id) { return mNoteService.deleteById(id); }Copy the code


Third, data return form optimization and unity and exception capture


1. The return form of the result is uniform
/ / success json: {" code ": 200," MSG ":" successful ", "data" : {" id ": 2," type ":" B ", "name" : "the BASE", "localPath" : "C ", "jianshuUrl": "http://jianshu", "juejinUrl": "http://juejin", "imgUrl": "imgUrl", "create": null}} // Failed json: { "code": 500, "msg": "/ by zero", "data": null }Copy the code


2. Unified format realization:
/** * Author: Zhang Feng Jiete Lie * Time: 2018/5/25:15:30 * Email: [email protected] * Description: Public class ResultBean<T> {private int code; private String msg; private T data; public ResultBean(int code, String msg, T data) { this.code = code; this.msg = msg; this.data = data; } // Get, set, toStringCopy the code
3. Use enumeration classes to maintain uniform error codes and error information

Maintains a number of error enumerations that can be customized to be thrown when exceptions are caught for administrative purposes

By default, querying a database without an ID does not cause an error. In this case, you can customize an exception with an unknown ID and catch it in the Service layer

/** * Author: Zhang Feng Jiete Lie * Time: 2018/5/25:17:36 * Email: [email protected] * Description: */ public enum ResultEnum {SUCCESS(200, "operation succeeded "), EXCEPTION(500," failed "), NOT_FOUND_ID(102, "not found ID "); private int code; private String msg; ResultEnum(int code, String msg) { this.code = code; this.msg = msg; } public int getCode() { return code; } public String getMsg() { return msg; }}Copy the code
/** * Author: Zhang Feng Jiete Lie * Time: 2018/5/25:17:14 * Email: [email protected] * Description: Public class NotFoundIdException extends RuntimeException {private int code; private static String msg = ResultEnum.NOT_FOUND_ID.getMsg(); public NotFoundIdException() { super(msg); } public int getCode() { return code; } public void setCode(int code) { this.code = code; }}Copy the code
Public Note byId (int id) {Note byId = mNoteDao.findByid (id); if (byId == null) { throw new NotFoundIdException(); } return byId; }Copy the code

4. Result processing class

This class is used to transform all results into ResultBean objects, achieving the unity of return values

/** * Author: Zhang Feng Jiete Lie * Time: 2018/5/30:18:37 * Email: [email protected] * Description: Public class ResultHandler {/** * convert object to ResultBean object ** @param o * @return */ public static ResultBean ok(Object o) { return new ResultBean(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMsg(), o); } /** * @param error * @return */ public static ResultBean error(ResultEnum error) {return new ResultBean(error.getCode(), error.getMsg(), null); } public static ResultBean error(String e) { return new ResultBean(ResultEnum.EXCEPTION.getCode(), e, null); }}Copy the code

5. Exception capture:

@ExceptionHandler and @ControllerAdvice will make all exceptions go here, and use ResultHandler to handle them uniformly

Here you can customize some exceptions for your project

/ / @ControllerAdvice public Class ExceptionHandle {@ExceptionHandler(value = Exception.class) @responseBody  public ResultBean handle(Exception e) { return ResultHandler.error(e.getMessage()); }}Copy the code

6. Wrap all returned results in the Controller as a ResultBean
@RestController @RequestMapping(value = "/api/android") public class NoteController { @Autowired private NoteService mNoteService; @PostMapping(value = "/note") public ResultBean addOne(@ModelAttribute Note note) { mNoteService.insertNote(note); return ResultHandler.ok(note); } @PutMapping(value = "/note/{id}") public ResultBean updateById(@PathVariable("id") Integer id, @ModelAttribute Note note) { mNoteService.updateNote(id, note); return ResultHandler.ok(note); } @GetMapping(value = "/note") public ResultBean findAll() { return ResultHandler.ok(mNoteService.findAll()); } @GetMapping(value = "/note/{id}") public ResultBean findById(@PathVariable("id") Integer id) { return ResultHandler.ok(mNoteService.findById(id)); } @DeleteMapping(value = "/note/{id}") public ResultBean deleteById(@PathVariable("id") Integer id) { return ResultHandler.ok(mNoteService.deleteById(id)); }}Copy the code

Five: optimization and supplement

1. Request a summary

In general, the interface has these: (domain name: http://192.168.43.60, port: 8089)

Query: all GET request query: http://192.168.43.60:8089/api/android/note query id = 1: http://192.168.43.60:8089/api/android/note/1 query type = C: http://192.168.43.60:8089/api/android/note/type/C to View in a name: http://192.168.43.60:8089/api/android/note/name/View insert: A POST request to insert data: http://192.168.43.60:8089/api/android/note changes: PUT request modify id = 1 data: http://192.168.43.60:8089/api/android/note/1 delete: The DELETE request DELETE the data of id = 1: http://192.168.43.60:8089/api/android/note/1Copy the code

SQL mapping using inline query and fuzzy query is as follows:

The dao, Service, and Controller operations are similar

<select id="findALL" resultType="toly1994.com.android_project.bean.Note">
   SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,createTime FROM android AS a
   INNER JOIN type AS t ON a.type = t.type_idx
</select>

<select id="findByType" resultType="toly1994.com.android_project.bean.Note">
   SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,createTime FROM android AS a
   INNER JOIN type AS t ON a.type = t.type_idx
   WHERE a.type=#{type}
</select>

<select id="findById" resultType="toly1994.com.android_project.bean.Note">
   SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,createTime FROM android AS a
   INNER JOIN type AS t ON a.type = t.type_idx
   WHERE a.id=#{id}
</select>

<select id="findByName" resultType="toly1994.com.android_project.bean.Note">
   SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,createTime FROM android AS a
   INNER JOIN type AS t ON a.type = t.type_idx
   where name LIKE concat(concat('%',#{name}),'%')
</select>
Copy the code

3. Access server resources
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void AddResourceHandlers (ResourceHandlerRegistry registry) {/ / in F: / SpringBootFiles/Image/if there is a Excalibar JPG images, then: / / 【 1 】 access: http://localhost:8080/imgs/Excalibar.jpg can access to the / / 【 2 】 in the HTML < img SRC = "imgs/Excalibar. JPG" > registry.addResourceHandler("/imgs/**").addResourceLocations("file:F:/SpringBootFiles/imgs/"); registry.addResourceHandler("/mp3/**").addResourceLocations("file:F:/SpringBootFiles/mp3/"); registry.addResourceHandler("/file/**").addResourceLocations("file:F:/SpringBootFiles/file/"); }}Copy the code


4. File upload interface:UploadController.java
Upload form: http://192.168.43.60:8089/api/android/upload write flow upload: HTTP: / / http://192.168.43.60:8089/api/android/postfile / / note that SpringBoot upload form has the limited size of 2 m, modify way: spring: servlet: multipart: max-file-size: 10MB max-request-size: 100MBCopy the code

@restController @requestMapping (value = "/ API /android") public class UploadController {/** * Upload form: @post Mapping(value = "/upload") public @responseBody ResultBean uploadImg(@RequestParam("file") List<MultipartFile> files) { StringBuilder result = new StringBuilder(); for (MultipartFile file : files) { if (file.isEmpty()) { return ResultHandler.error("Upload Error"); } String fileName = file.getOriginalFilename(); String path = "F:/SpringBootFiles/imgs/"; File dest = new File(path + "/" + fileName); if (! Dest.getparentfile ().exists()) {// Check whether the parent directory of the file exists dest.getparentfile ().mkdir(); } try { file.transferTo(dest); // Save the file result.append(fileName).append(" Upload succeeded! \n"); } catch (IllegalStateException | IOException e) { e.printStackTrace(); Result.append (fileName).append(" Upload failed! \n"); } } return ResultHandler.ok(result.toString()); } /** * Write to server via stream * @param name * @param request * @return */ @postMapping (value = "/postfile") public @responseBody ResultBean postFile(@RequestParam(value = "name") String name, HttpServletRequest request) { String result = ""; ServletInputStream is = null; FileOutputStream fos = null; try { File file = new File("F:/SpringBootFiles/imgs", name); fos = new FileOutputStream(file); is = request.getInputStream(); byte[] buf = new byte[1024]; int len = 0; while ((len = is.read(buf)) ! = -1) { fos.write(buf, 0, len); } result = "SUCCESS"; } catch (IOException e) { e.printStackTrace(); result = "ERROR"; } finally { try { if (is ! = null) { is.close(); } if (fos ! = null) { fos.close(); } } catch (IOException e) { e.printStackTrace(); } } return ResultHandler.ok(result); }}Copy the code


4. Cross-domain processing

The cross-domain problem is mainly the request header problem, detailed analysis visible: Springboot-12 – Ajax cross-domain access full resolution

AndroidProjectApplication
@mapPerscan (basePackages = {"toly1994.com.android_project.dao"}) public class AndroidProjectApplication { public static void main(String[] args) { SpringApplication.run(AndroidProjectApplication.class, args); } @Bean public FilterRegistrationBean registerFilter() { FilterRegistrationBean bean = new FilterRegistrationBean(); bean.addUrlPatterns("/*"); // All requests go through this Filter bean.setFilter(new CrosFilter()); // Set the filter return bean; }}Copy the code
toly1994.com.android_project.config.CrosFilter
/** * Author: Zhang Feng Jiete Lie * Time: 2018/7/22:21:44 * Email: [email protected] * Description: Solve cross-domain problems... */ public class CrosFilter implements Filter {@override public void init(FilterConfig FilterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletResponse rep = (HttpServletResponse) servletResponse; HttpServletRequest req = (HttpServletRequest) servletRequest; String origin = req.getHeader("Origin"); if (! StringUtils.isEmpty(origin)) { rep.addHeader("Access-Control-Allow-Origin", origin); } String headers = req.getheader (" access-control-request-headers "); if (! StringUtils.isEmpty(headers)) { System.out.println(headers); rep.addHeader("Access-Control-Allow-Headers", headers); // rep.addHeader(" access-control-allow-origin ", "*"); // rep.addHeader("Access-Control-Allow-Origin", "http://localhost:8081"); GET rep.addHeader(" access-control-allow-methods ", "GET"); rep.addHeader("Access-Control-Allow-Methods", "POST"); // rep.addHeader("Access-Control-Allow-Headers", "Content-Type"); rep.addHeader("Access-Control-Max-Age", "3600"); Rep. addHeader(" access-control-allow-Credentials ", "true"); // Allow cookie filterchain.doFilter (servletRequest, rep); } @Override public void destroy() { } }Copy the code

4. Deploy the local SpringBoot project to the server (using Tencent Cloud)

1. Packing:

I changed the port to 8089(because my server has port 8089 on)

mvn -Dmaven.test.skip -U clean install
Copy the code

2. Back up and restore the database

Local backup and server recovery

Backup: mysqldump -uroot -p mycode >D:\\backupSql\\android.sql restore: mysql -uroot -p mycode< D:\\backupSql\\android.sqlCopy the code


3. Online

Run:

F: \ > Java jar - F: \ android_project - 0.0.1 - the SNAPSHOT. The jarCopy the code

4. Test the URL API
1) Add: POST:www.toly1994.com:8089/api/android…

2) query:www.toly1994.com:8089/api/android…

3) Access pictures

So far the back-end database simple operation and RESTFUl API interface has been implemented, although relatively simple

Later there is a need to add other URLS, access interfaces have data, the back end from this end.


2018-12-12 Added: Add paging query:

Offset 0, a page of article 20 data: http://192.168.43.60:8089/api/android/note/0/20

<select id="findByType" resultType="toly1994.com.android_project.bean.Note">
   SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,info,createTime FROM android AS a
   INNER JOIN type AS t ON a.type = t.type_idx
   WHERE a.type=#{type}
   limit #{offset},#{limit}
</select>
Copy the code

Classification of query page: http://192.168.43.60:8089/api/android/note/type/ABCS/0/4

<select id="findByName" resultType="toly1994.com.android_project.bean.Note">
   SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,info,createTime FROM android AS a
   INNER JOIN type AS t ON a.type = t.type_idx
   where name LIKE concat(concat('%',#{name}),'%')
   limit #{offset},#{limit}
</select>
Copy the code

Python Crawler + Data Preparation (Selenium)


Postscript: Jie wen standard

1. Growth record and Errata of this paper
Program source code The date of note
V0.1 2018-12-11 Site construction tetralogy of back-end interface (SpringBoot+ online)
V0.2 2018-12-12 Add info field to paging query processing
2. More about me
Pen name QQ WeChat hobby
Zhang Feng Jie te Li 1981462002 zdl1994328 language
My lot My Jane books I’m the nuggets Personal website
3. The statement

1—- This article is originally written by Zhang Fengjie, please note if reproduced

2—- welcome the majority of programming enthusiasts to communicate with each other 3—- personal ability is limited, if there is something wrong welcome to criticize and testify, must be humble to correct 4—- see here, I thank you here for your love and support