当前位置:网站首页>Ruiji takeout notes
Ruiji takeout notes
2022-07-04 14:18:00 【Fengyin Pro】
summary
Functional architecture

Database building, database building and table building
Table description

development environment
Maven build
Directly create a new project
Inherit the form of the parent project to do this , Create a new parent project here 
pom file
server:
port: 9001
spring:
application:
name: ccTakeOut
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ruiji?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 333
redis:
host: localhost # Local IP or virtual machine IP
port: 6379
# password: root
database: 0 # By default 0 Number db
cache:
redis:
time-to-live: 1800000 # Set the expiration time of cached data ,30 minute
mybatis-plus:
configuration:
# When mapping entities or attributes , Remove the underscores from the table names and field names in the database , Turn on mapping according to hump nomenclature
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
id-type: ASSIGN_ID
Start the test
Create a test class and start 
Import the front page

Import
In the case of default page and foreground page , Drag these two directly to resource Direct access under the directory is not accessible , Because being mvc The framework intercepted
So we need to write a mapping class to release these resources
Create a configuration mapping class


Successful visit 
The background and development
Database entity class mapping
use mybatis plus To realize reverse engineering
Here is the old version of Reverse Engineering
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<!--mybatis-plus The code generator depends on -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.2</version>
</dependency>
How to play depends on here
MP Reverse engineering course 
Account operation
Landing function
Front page 


database 
Business logic 
The comparison between the two strings here is useless != To achieve , Can only equals Then take the opposite to judge
Go straight to the code , There is no reference to service The operation of the layer
/** * @param request If the login succeeds, put the object into Session in , Convenient for subsequent taking * @param employee utilize @RequestBody Annotation to parse the data from the front end Json, At the same time, use objects to encapsulate * @return */
@PostMapping("/login")
public Result login(HttpServletRequest request, @RequestBody Employee employee) {
String password=employee.getPassword();
String username = employee.getUsername();
log.info(" land ");
//MD5 encryption
MD5Util md5Util = new MD5Util();
password=MD5Util.getMD5(password);
// Check the employee object through the account , Don't go here Service The layer
LambdaQueryWrapper<Employee> lambdaQueryWrapper = new LambdaQueryWrapper();
lambdaQueryWrapper.eq(Employee::getUsername, username);
Employee empResult=employeeService.getOne(lambdaQueryWrapper);
// Judge whether the user exists
if (!empResult.getUsername().equals(username)){
return Result.error(" Account does not exist ");
// Is the password correct
}else if (!empResult.getPassword().equals(password)){
return Result.error(" Wrong account password ");
// Whether the employee account status is normal ,1 Normal state ,0 Prohibition
}else if (empResult.getStatus()!=1){
return Result.error(" The current account is being blocked ");
// Login is allowed when the status is normal
}else {
log.info(" Landing successful , Account deposit session");
// staff id Deposit in session,
request.getSession().setAttribute("employ",empResult.getId());
return Result.success(" Landing successful ");
}
}
For specific code, please refer to the following path
com.cc.controller.EmployeeController
Exit function
Click to exit 
Delete session object
/** * @param request Delete request scoped session object , Just press login request.getSession().setAttribute("employ",empResult.getId()); Delete employee Just go * @return */
@PostMapping("/logout")
public Result login(HttpServletRequest request) {
// Try to delete
try {
request.getSession().removeAttribute("employ");
}catch (Exception e){
// Delete failed
return Result.error(" Logout failed ");
}
return Result.success(" Log out successfully ");
}
Perfect login ( Add filter )
Here, the user directly url+ The resource name can be accessed casually , So we need to add an interceptor , When there is no login , No access , Automatically jump to the login page 
Filter configuration class annotation @WebFilter(filterName=" Interceptor class name is lowercase ",urlPartten=“ The path to intercept , such as /*”)
Before judging the login status of users, it was saved session There's a name in it employee The object of , Then just look at this session Whether he is logging in or not is known
Be careful , If you want to save or get , You have to use them all HttpServletRequest Object to get , other request Objects are not available
Here's a word
call Spring The string of the core package matches the object of the class , Match paths , And return the comparison result
If it is equal, it is true
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

The front-end interceptor finishes jumping to the landing page , Do not process at the back end 
There's too much code , Give me a path , Go directly to Gitee see
request Of js Code path :resource/backend/js/request.js
The path of the interceptor :com.cc.filter.LoginCheckFilter
New employees
New employee function ,( The front end verifies the length of the mobile phone number and ID number )
request URL: http://localhost:9001/employee (POST request )

modified Employee Entity class , Universal id Snowflake auto increment algorithm to add id
Here we use service Interface inherited MybatisPlus The function of 
It can be used after injection , Insert method 
Basically, they are automatic CRUD, Access path :com.cc.controller.EmployeeController
Global exception handling
Take a look at this code first try catch
such try catch It's good to catch exceptions , however , A lot of code , Super much try catch It's going to be messy 
So we need to add global exception handling , stay Common It's a bag , and Result At the same level , This is just an example , Incomplete 

When the error message appears Duplicate entry when , It means that the new employees are abnormal
therefore , We make some small changes to the methods of exception classes , Make this abnormal feedback more humanized 
Try the client again at this time , It will provide humanized error reporting , Very happy ~
This time, I'll go back to Controller, There is no need to come again try catch This is the form , Don't worry about him , Because once there is a mistake, it will be our AOP Capture . therefore , There is no need to use try catch Here we go 
Exception class location :com.cc.common.GloableExceptionHandler
Paging query of employee information
Interface Analysis
It's a clich é about paging queries
demand 
Paging request interface 

Query employees and display interface 

Logical process 
Paging plug-in configuration class
To get a first MP Paging plug-in configuration class
The reason is and 3.2.3 Version of code generator conflicts
Paging plug-ins are popular solutions 
Comment out 
Add configuration class 
Interface design
Front end considerations 

page Inside object 
It includes the use of query constructors
The specific details are under this package :com.cc.controller.EmployeeController.page
/** * The employee list interface is displayed in pages 、 Query an employee * @param page Look up the page * @param pageSize There are several pieces of data on each page * @param name Search for names =name The data of * @return return Page page */
@GetMapping("/page")
public Result<Page> page(int page, int pageSize,String name){
// Paging constructor ,Page( Page , Check a few )
Page pageInfo = new Page(page, pageSize);
// Query builder
LambdaQueryWrapper<Employee> lambdaQueryWrapper = new LambdaQueryWrapper();
// Filter conditions .like( Under what conditions are fuzzy queries enabled , Fuzzy query fields , The name that was vaguely interpolated )
lambdaQueryWrapper.like(!StringUtils.isEmpty(name), Employee::getName, name);
// Add sort
lambdaQueryWrapper.orderByDesc(Employee::getCreateTime);
// Query page 、 Auto update
employeeService.page(pageInfo, lambdaQueryWrapper);
// Return query results
return Result.success(pageInfo);
}
Enable 、 Disable employee account
Nothing more than modification status,0 Ban ,1 Enable 

This kind of play method of Judging according to the landing characters , Is the front
The location of this page resource/backend/page/member/list.html
See what the object looks like , If it is admin,vue Of v-if The command will display the Edit button
If it is an ordinary user , Will hide the Edit button 
Fix a little Bug
The Edit button is not displayed on the front end , stay localStorage No admin object 
This value should not be login success , Should be Employee The object of Json
Guess it's when you land request The object stored in the file is not saved well 
Just change it to object storage 
It's all normal this time 
Function writing
Review the
PutMapping yes Resultful Style of request 
The current status is 1, Take the target state value directly ( The status changes to disabled ) updated 
Id Precision loss ,js Unique bug, Deal directly with Long Can't handle , want Long turn String Go back to 

Using object converters JacksonObjectMapper, Turn the object to Json
take Long Type Id Convert to String Data of type 
stay MVC Extend a message converter in the configuration class 
The test function is normal , Update employee status normally
Message extender configuration location :com.cc.common.JacksonObjectMapper
Object mapper location :com.cc.config.WebMvcConfig
Employee status update location :com.cc.controller.EmployeeController
Edit employee information

request API, This is the first request , Find out the user , Then fill in the page
You can see it , This kind of request is ResultFul Style of request
Use in the controller @PathVariable(“/{ Parameter name }”) Comments to receive 

Perfect update
Update method location :com.cc.controller.EmployeeController.getEmployee
The public fields are automatically populated
Like some public fields , It makes no sense to fill it up repeatedly , Simplify the filling operation .
Take out this function , Carry it out alone for automatic filling 

Annotate the entity class attributes @TableField(fill = Filling conditions )
Look at the source code .fill Is the filling condition , Enumerations are used for processing 
Adding comments and conditions is not the end , Also add configuration classes for processing , Specify the filled data
stay common Create a custom class under the package , The key is to achieve MetaObjectHandler Under interface insertFill and updateFill
Confirm the fields required for filling . And I want to join @Component annotation , Leave this class to the framework to manage , Otherwise, it is easy to find ,setValue The value of will lock whether it needs to be updated according to the field name added in the annotation
Location :com.cc.common.MyMetaObjectHandler
But there's a problem , If I want to update the administrator field, it is very difficult , Because I can't get it here Request Scope object for , So we need to find a way to deal with .
This is the time ThreadLocal To obtain objects , This thread runs through the whole run , You can get it through him
When using
What is the ThreadLocal
The key is coming.
This figure 

My idea is when users log in , Put this id Put into , Wait until the field is filled , from ThreadLocal Take this resource out again .
Direct operation is not good , Package it into a tool class , The methods in this tool class are static , You can call... Directly through the class 、 And they are all static methods , To save and read
I choose Utils Create
For the first time Bug
The specific package is utils in , Yes Bug, Encapsulated classes ThreadLocal Data not available , I'm not sure why , Write this down for the time being
// be based on ThreadLocal Wrapper utility class , The user saves and obtains the currently logged in user id
// ThreadLocal Take thread as Scope , Save a copy of the data in each thread
public class BaseContext {
private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
// Set the current user id
public static void setCurrentId(Long id){
threadLocal.set(id);
}
public static Long getCurrentId(){
return threadLocal.get();
}
}
Be careful ,ThreadLocal Not a thread , Only the same thread can get , It's not something a thread can't get
Solution
change setId The location of , Store it inside the filter , Even a thread , Can get . But I have tried , It's really a thread , But I still can't get it .
Change the way of thinking : Because I want to take Request In the object Id Well , therefore , As long as there is Request Of id Just go , Don't be too persistent, you must use ThreadLocal Come and save , therefore , I choose to inject here HttpServletRequest Object to solve this problem .
Dishes page
Classification of dishes

The tables involved are classification tables category
The business process 
New dish classification
The request mode is Post request 

Controller position :com.cc.controller.CategoryController (save)
Show the dishes by category

Still those steps
- Create paging constructor Page pageInfo = new Page( Page , A few pieces of data per page );
- If you need conditional filtering, add conditional filter LambaQueryWarpper
- Injected service object ( Inherited MP Of BaseMapper Interface ) To call Page object
service object .page( Paging information , Conditional filter ) - Just return the result
Paging query location :com.cc.controller.CategoryController.page
Delete dish classification


Normal version , There is no consideration of the relevance of classification 
Perfect it , If there are dishes under the current dish classification , You are not allowed to delete
So before deleting, you must make a judgment before deleting , Do not meet the conditions , We need to throw an exception to prompt
Because there is no class that returns exception information , Here we need to make a custom class that specially returns exception information CustomerException
The location of this class is also common It's a bag 
Because we created a global exception handler before , Also use , Because we need to intercept exceptions for unified processing
still com.cc.common.GloableExceptionHandler
Handle exceptions thrown , You can provide target interception and exception notification for new exceptions 
Delete dishes classified controller Interface in :com.cc.controller.CategoryController (delCategory)
Because of the special business , And relatively long , Just separate and put the business in service It's a bag
service Interface location :com.cc.service.impl.CategoryServiceImpl (removeCategory)
Modify package information

Very simple CRUD, Call directly MP Just update it
API Location
com.cc.controller.CategoryController (updateCategory)
File upload download ( a key )
Upload logic
First contact with upload and download functions
File upload logic ( Back end )
Parameter name is required
The type of file received must be Method name (MultipartFile The name of the file uploaded by the front end )

Therefore, the receiving name of the backend must also be changed to file
Upload logic implementation
The specific storage path is written in the configuration file 
use @Value Just inject it into the business 
The specific location is com.cc.controller.CommonController (upLoadFile)
Download logic

Picture echo function
Input and output streams are used
Location :com.cc.controller.CommonController (fileDownload)
Menu management page
New dishes
Demand analysis

The involved table is dish and dish_flavor
Development logic 
New implementation
Because it is a multi table operation ,MP You can't do it directly , So put service Layers are extracted for processing
also , Because it involves two tables , There are also transactions to control , Prevent multi table operation from crashing
Multiple table operations can only be performed one by one ,MP There is no way to operate multiple tables at once
Because it involves multiple tables , So we need to add annotations to deal with transactions
@Transactional Open transaction
@EnableTransactionManagement Add... In the startup class , Support transaction startup
Controller Location :com.cc.controller.DishController (addDish)
Service Location :com.cc.service.DishService
ServiceImpl Location :com.cc.service.impl.DishServiceImpl (addDishWithFlavor)
New dishes to get the types of dishes

Receive one from the front end type=1 The annotation , The purpose is in the classification table , The classification of dishes is 1, The package classification is 2, Distinguish the two , Get all types of dishes 
Location :com.cc.controller.CategoryController (listCategory)
Dish sorting
I also made the dishes in different pages , Don't write too much , Position in :com.cc.controller.CategoryController (dishPage)
Record a knowledge point , If there is no class on the back end corresponding to the data on the front end , Then you can encapsulate a class to encapsulate the data required by the front end
DTO object
This class can extend some entity classes , Inherit from a parent class , Add some more
such as Dish and DishDto
DishDto Inherit from Dish class , And on this basis, it is extended 

Update dish information
That's it. update
Logic 
Be careful , The echo data here is to use DishDto, Because the front end should display information such as taste , If you use Dish It cannot be displayed perfectly , So want to use DishDto
Echo fill query

besides , This is a multi table joint query , use MP Definitely not , I have to write it myself
Controller Location :com.cc.controller.DishController (updateDish)
Service Location :com.cc.service.DishService
ServiceImpl Location :com.cc.service.impl.DishServiceImpl
Update implementation
In fact, it is the simultaneous update and deletion of two tables , therefore MP Direct operation is not allowed , So we need to Service The layer itself encapsulates a deletion method , to Controller Just delete the layer call
about Dish Objects can be updated directly , because DishDto yes Dish Subclasses of
So you can call DishService Of update Methods the incoming DishDto object , To achieve Dish Update
Controller Location :com.cc.controller.DishController (updateDish) It's really the same as the one above , Because the way of request is different
Service Location :com.cc.service.DishService
ServiceImpl Location :com.cc.service.impl.DishServiceImpl (updateDishWithFlavor)
Other features
Complete the development of some small functions 
Stop selling function
That is to put the database status Update the value , Two paths , One for sale , One stop 
Stop selling request path 
If the state is different , It will change from stop selling to start selling , At the same time, the corresponding request path is also different 

Controller Location :com.cc.controller.DishController (updateStatusStop) stop it
Controller Location :com.cc.controller.DishController (updateStatusStart) start-up
Delete function

Dish deletion function
Complete logical deletion , Not really delete 
Location :
Controller Location :com.cc.controller.DishController (deleteDish) stop it
Package page
It's actually a collection of dishes
Overview of new packages
Database involved 


Import SetmealDto

Add the menu of the set menu


Controller Location :com.cc.controller.DishController (listCategory)
The new package realizes
It's similar to the new dishes , Here is also the operation of multiple tables
Controller Location :com.cc.controller.SetmealController (saveSetmeal)
Service Location :com.cc.service.SetmealService
ServiceImpl Location :com.cc.service.impl.SetmealServiceImpl(saveWithDish)
Package paging
The pagination of the package here is different from that in the past , Design to multi table content 
Package paging Controller Location :com.cc.controller.SetmealController.pageList
package Mapper Interface location :com.cc.mapper.SetmealMapper
Mapper file location :resource.mapper.SetmealMapper
Update package
Adding packages and updating packages are almost identical , The fields of barabara are the same 
But notice , Modify the package , You need to fill in the dishes page first , This page needs to be filled with the information of the dishes to be modified .
First request , A see be Restful Style request 
Get the package Controller Location :com.cc.controller.SetmealController.getSetmal
Update sales status


It is very similar to the previous business logic , I don't want to go into details , Put it directly at the interface
Controller Location :com.cc.controller.SetmealController (startSale/stopSale)
Delete package
It can be deleted separately , You can also delete in batch , The interface is all gold , Can connect , It mainly depends on the data transmitted 

Interface 
== Multi table delete , stay Controller Direct implementation is not realistic , So we need to Service Write the business well ==
Controller Location :com.cc.controller.SetmealController (deleteSetmeal)
Service Location :com.cc.service.SetmealService
ServiceImpl Location :com.cc.service.impl.SetmealServiceImpl(removeWithDish)
The front desk development ( Mobile terminal )
Account login
Text messaging


Alibaba cloud SMS service tutorial
Code implementation
Official document address
Import Maven
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.16</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.1.0</version>
</dependency>

Import the tool class of SMS login , hold ACCESSKeyID and Secret Just replace it in place 
Verification code sending
Data model user surface , A special table for mobile phone verification code 
Development process 
Modify interceptor , Release operation 

controller Location :com.cc.controller.UserController (sendMsg)
After sending, you need to verify , Verification is another login 了
The user login

controller Location :com.cc.controller.UserController (login)
Login here also involves the function of filter release , Don't forget , Put the user id Deposit in session, The filter will be validated
filter 
controller
Foreground page
Import user address book

Address table 
Here you can import the ready-made AddressBookController, I didn't write it myself
com.cc.controller.AddressBookController
Food display
Logical combing 

modify DishController Of list Method , To meet the requirements of the front desk request
controller Location :com.cc.controller.DishController (listCategory)
Set menu dishes Controller:com.cc.controller.SetmealController (list)
The shopping cart
Add the dishes to the shopping cart 

Logical combing 
Be careful , There is no need for the back end to calculate the total price , It's the unit price * Quantity of this operation , Not the content of the back end . The front end calculates by itself when it is displayed .
Location :com.cc.controller.ShoppingCartController (add)
Place an order

The corresponding two tables , One is orders surface , The other is orders_detail surface
orders surface 
orders_detail surface 
Interaction process 
The business is more complex , stay Service It's written in English com.cc.service.impl.OrdersServiceImpl
So far, the basic part is completed , Start optimizing project performance
Summary of small knowledge points
@RequestBody Use
Only the parameter passed is Json Ability to use RequestBody receive , If not Json The situation of ( Like that ?key=value&key=value) It can't be used , Meeting 400 error
About RequestBody When to use
Cache optimization
be based on Redis Cache optimization 
Environment building
Redis To configure
Join in Pom file
<!-- Import Redis rely on -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Join in Redis Configuration class
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
// default Key The serializer is :JdkSerializationRedisSerializer
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
}
yml Add configuration 
SMS verification code 、 Login optimization
Add valid time verification to the verification code , Set the effective time of SMS verification code 
If the login is successful , Automatically delete the verification code in the cache
Optimize the location :com.cc.controller.UserController sendMsg and login
Inject RedisTemplete
Optimize the verification code 
Optimize after login
login In the method 

The filter here should also be changed , Because of the login id Data from session Turned into redis Deposit , Therefore, the relevant parts of the filter should be transformed
com.cc.filter.LoginCheckFilter
It is also necessary to inject RedisTemplate
Cache the foreground dish data

Cache ideas , Ensure that the cache database and DBMS Keep the data in sync , Avoid reading dirty data ( No updated data )
Yes DishController To optimize , Added cache
Visit again to find , If the current dish classification has been cached , You won't check the database anymore
Update the dishes and update the cache
Ensure less dirty data , So add clean cache , If it is not cleaned in time , Save the new data , The list database cannot be updated synchronously . There will be problems .
Here we clean up the precise data . Large area cache clearing is also more performance intensive
This is full cleaning 
This is precision cleaning 
SpringCache
brief introduction

SpringCache Common annotations and functions

Fast start
Add... To the startup class @EnableCaching annotation , Enable caching framework 
@CachePut annotation
Cache method return value , Cache one or more pieces of data 
@CacheEvict annotation
Delete cache 
@Cacheable annotation
Have a look first Spring Whether the current data has been cached , If it has been cached, return directly .
If there is no cache, cache it directly into memory 
Some special circumstances ,condition Properties and Unless attribute 
The front is used SpringCache Built in cache container , Performance is definitely not comparable Redis
So now start introducing Redis As SpringCache Cached products
Switch to a Redis As a cache product
SpringCache-Redis

Import jar package 
Inject the corresponding cache product Manager That's all right. , Here we use RedisManager For example 
utilize SpringCache-Redis To cache package data

Add... To the startup class @EnableCaching annotation , Enable caching framework 
Pit when adding notes
Here is equivalent to from Return Get in the Setmeal Properties in , however Return When the data is Result Packaged Setmeal data , Obviously, serialization cannot be completed , Here also need to be right Result Class to serialize 
Inherit serialization class , Make it serializable 
= At this point, the optimization of the cache is completed , At this time, if there is current value Cache of names , It will automatically return to , If not, just check . The current cache expires automatically at yml There are detailed configurations
Save package method cache optimization
1. Save the package , The corresponding cache must be deleted , Because the data is updated, it needs to be retrieved
There are also updated packages , For the same reason
The deletion method needs to add 
The preservation method should also be added 
Database optimization
MySQL Read / write separation
Change the single point database into a distributed database server
Write and read .

MySQL Master and slave copy build
Master database settings
Master slave replication architecture diagram 
The above can achieve the synchronization of master database data and slave database data
Configure the main library
Linux Reform the law 
log-bin=mysql-bin # Start binary
server-id=100 # only id

windows Reform the law
stay mysql Under installation path 

After modification, restart MySQL

windows The restart tutorial of version is here
restart mysql
=======================================================

GRANT REPLICATION SLAVE ON*.*to'xiaoming'@'%'identified by '[email protected]';
Here I put the local MySQL As a host , Take Alibaba cloud as a slave
Run the permission SQL
Check the host status show master status;
From library settings
Select Alibaba cloud from the Library
Or modify the configuration file first , Join the port id

The second step is to restart from the Library (Linux in )
Third parts , Set up connection to the host
function SQL
Run it
Specifically, you can use the slave show master status see
change master to master_host='ip',master_user='xiaoming',master_password='[email protected]',master_log_file='mysql-bin.eo0001',master_log_pos= The host position


Here I have two servers , a docker Installed mysql( Slave )
The other one is normally installed mysql Be the host , There are many problems in the configuration process , Refer to the following link
Reference tutorial
Be sure to remember to start the slave after the above slave connection command runs successfully, that is
slave start
Last run start slave Even if the implementation is successful 
Check the slave status
show slave status
In this way, it will be built 
test



Even if the construction is completed here
Problems encountered
The problem here , Not even 
Want to be a local host , It doesn't seem very good to be a slave on the Internet , I got another server to do read-write separation
After getting the slave , Start configuration , install MySQL wait
Sometimes it will prompt io Conflict , This is because the previous slave was not shut down , Just close it stop slave once It's ready to run
A slave boot command was forgotten , Changed all night
If you do not run the slave boot, it will become like this 
Write mainly and read practically
summary

How hard is it to decide SQL Which library should be assigned , It depends on Sharding-jdbc Framework to separate read and write processing 
actual combat
Steps are as follows 
Import Maven coordinate
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.0-RC1</version>
</dependency>
To configure yml file
spring:
application:
name: ccTakeOut
shardingsphere:
datasource:
names:
master,slave
# Main library ( Add, delete and change operation )
master:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://121.89.200.204:3306/ruiji?characterEncoding=utf-8
username: root
password: 333
# From a data source ( Read operations )
slave:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://121.36.51.170:3306/ruiji?characterEncoding=utf-8
username: root
password: 333
masterslave:
# Read write separation configuration
load-balance-algorithm-type: round_robin # polling ( If there are multiple slave libraries, they will poll for reading )
# The final data source name
name: dataSource
# Main database data source name
master-data-source-name: master
# From the list of library data source names , Multiple commas separate
slave-data-source-names: slave
props:
sql:
show: true # Turn on SQL Show , Default false
main:
allow-bean-definition-overriding: true # allow bean Data source coverage
Read about the yml To configure 
allow Bean Defining coverage is important
test
Start project , You can see , The read and write operations have reached different hosts
Read-write separation test 

Nginx Deploy
Separate front and rear development


Development process

YApi

Swagger( Commonly used )
Its main function is to help backend personnel generate backend interface documents 
Usage mode 
Import coordinates
<!--knife4j Interface management -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
Import configuration class 
Specific configuration location com.cc.config.WebMvcConfig
Start the service , Access path +doc.html
After entering, you can manage the existing interfaces 
Swagger Commonly used annotations
The directly generated annotation content is not very perfect 
Swagger Commonly used annotations 
Take entity classes as an example 
Controller The annotations on 
The above are examples , Finally perfect the annotation , Documents will be better used , A more detailed .
Project deployment
front end
Front end as a project , You also need to pack , Packed as dist Catalog 
Put this dist Catalog , Thrown into Nginx in HTML Folders will do , That is, the static resource 
It's not over when you pass it on , We need to configure it well
One is static resources , The other is reverse proxy
Static resource allocation
First configure static resources 
Request agent configuration
restart Nginx, Test it , visit .
Any request can see , With a prefix 
The port given by the backend project is 9001
The request path is :http://www.ccsmile.fun:9001/api/employee/login
We don't have this on the back end api The prefix of
By rewriting url, You can put the http://www.ccsmile.fun:9001/api/employee/login
become http://www.ccsmile.fun:9001/employee/login Request address of , This completes the request proxy forwarding operation 
The configuration file is as follows
server{
listen 80;
server_name localhost;
# Static resource allocation
location /{
root html/dist;
index index.html;
}
# Request forwarding agent , rewrite URL+ forward
location ^~ /api/{
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http:// The back-end service ip: Port number ;
}
# other
error_page 500 502 503 504 /50x.html;
location = /50x.html{
root html;
}
}
Last save the file , restart Nginx, The configuration is complete
But I still don't know why it's not easy to use , It still needs to be solved , If not, just add the receive request prefix to the backend
Back end

Upload script , Automatically pull the latest script
In this way, on the development side and Linux The end passes Gitee Indirectly realize synchronization 
The script content
#!/bin/sh
echo =================================
echo The automated deployment script starts
echo =================================
echo Stop the original running project
APP_NAME=reggie_take_out
tpid=`ps -ef|grep $APP_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
if [ ${tpid} ]; then
echo 'Stop Process...'
kill -15 $tpid
fi
sleep 2
tpid=`ps -ef|grep $APP_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
if [ ${tpid} ]; then
echo 'Kill Process!'
kill -9 $tpid
else
echo 'Stop Success!'
fi
echo Ready to go from Git The warehouse pulls the latest code
cd /usr/local/javaapp/reggie_take_out
echo Start from Git The warehouse pulls the latest code
git pull
echo Code pull complete
echo Start packing
output=`mvn clean package -Dmaven.test.skip=true`
cd target
echo Start project
nohup java -jar reggie_take_out-1.0-SNAPSHOT.jar &> reggie_take_out.log &
echo Project start up complete
Execute the script OK 了 
Remember to revise yml Part of the document , Such as file path and other information ~
It's over and flowers are scattered
边栏推荐
- Use the default route as the route to the Internet
- mac redis安装与使用,连接远程服务器 redis
- Install MySQL
- Understand chisel language thoroughly 03. Write to the developer of Verilog to chisel (you can also see it without Verilog Foundation)
- Understand chisel language thoroughly 07. Chisel Foundation (IV) - bundle and VEC
- R语言使用dplyr包的group_by函数和summarise函数基于分组变量计算目标变量的均值、标准差
- The font of markdown grammar is marked in red
- php 日志调试
- 去除重複字母[貪心+單調棧(用數組+len來維持單調序列)]
- 按照功能对Boost库进行分类
猜你喜欢

Innovation and development of independent industrial software
![[FAQ] summary of common causes and solutions of Huawei account service error 907135701](/img/43/1a9786c89a5ab21d1fb8903cb7b77e.png)
[FAQ] summary of common causes and solutions of Huawei account service error 907135701

Unittest框架中引入TestFixture

2022 practice questions and mock exams for the main principals of hazardous chemical business units

92.(cesium篇)cesium楼栋分层

Unity Shader学习(三)试着绘制一个圆

基于PaddleX的智能零售柜商品识别

Unittest中的TestSuite和TestRunner

DDD application and practice of domestic hotel transactions -- Code

Test evaluation of software testing
随机推荐
Matters needing attention in overseas game Investment Agency
做事的真正意义和目的,真正想得到什么
Mongodb commonly used 28 query statements (forward)
【FAQ】华为帐号服务报错 907135701的常见原因总结和解决方法
What is the real meaning and purpose of doing things, and what do you really want
Migration from go vendor project to mod project
MATLAB中tiledlayout函数使用
2022 game going to sea practical release strategy
Use of arouter
Assertion of unittest framework
学习项目是自己找的,成长机会是自己创造的
去除重複字母[貪心+單調棧(用數組+len來維持單調序列)]
【Matlab】conv、filter、conv2、filter2和imfilter卷积函数总结
Understand chisel language thoroughly 05. Chisel Foundation (II) -- combinational circuits and operators
Understand chisel language thoroughly 11. Chisel project construction, operation and test (III) -- scalatest of chisel test
Basic mode of service mesh
数据仓库面试问题准备
测试流程整理(2)
为什么图片传输要使用base64编码
Golang 使用 JSON unmarshal 数字到 interface{} 数字变成 float64 类型(转)