当前位置:网站首页>Can you believe it? It took me only two days to develop a management system
Can you believe it? It took me only two days to develop a management system
2022-06-12 14:30:00 【Java notes shrimp】
Click on the official account , utilize Fragment time to learn
Difficulty analysis
Although, when I heard the news , I'm still shocked , After all, it is a complete management system , The function interface should not be too simple . And from the database design to the delivery of the whole system is completed by one person , The challenge effect will directly fill ! But calm down and think , It's not that hard , The overall project process is : Design ——> file ——> code ——> deliver .
After the overall process is clarified , Start to realize from scratch step by step , I didn't expect the last step , I only spent a day and a half !! Later, it took half a day to optimize the overall project !
Project review
Final effect demonstration :

Technology selection :
SpringBoot
Thymeleaf
Mybatis-Plus
MySQL
PageHelper
Lombok
Redis( Later page optimization )
Project business process introduction
Login module 、 User module management and user role assignment , Management of news announcement module 、 Commodity module ( Including goods 、 Classification of goods 、 Order ) Management of 、 Management of role module ; Whether the front-end resource has permission to operate the resource , It uses thymeleaf Template syntax for judgment and identification, file upload and other basic functions .
Project structures, ( Using a template engine )
1. First create Maven project
Introduce corresponding dependencies , Build the required file directory


2. To write yaml The configuration file
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/supplier?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
username: root
password: root
# thymeleaf To configure
thymeleaf:
# Turn off caching
cache: false
prefix: classpath:/templates/
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml3. The initial stage of the project is basically built
At the beginning of building a project , In order to make the system appear more standardized , I usually make the basic configuration and declaration in advance , The technologies involved in a project from the beginning and some basic configurations corresponding to these technologies , We should plan clearly in advance ( Personal habits ). such as : exception handling 、 Interceptor 、 filter 、 Constant classes, etc .
① exception handling
@ControllerAdvice
public class ExceptionHandler {
private final org.slf4j.Logger logger = LoggerFactory.getLogger(this.getClass());
@org.springframework.web.bind.annotation.ExceptionHandler(Exception.class)
public ModelAndView exception(HttpServletRequest request, Exception e ) throws Exception {
logger.error("Request URL:{},Exception:{}",request.getRequestURL(),e);
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class )!= null){
throw e;
}
ModelAndView mv = new ModelAndView();
mv.addObject("url",request.getRequestURL());
mv.addObject("exception",e);
mv.setViewName("error/error");
return mv;
}
}② Interceptor
Interceptors are mainly used to process some resources , Similar to some resources that require users to log in before they can access , Some are not needed , such as : The login function does not need to be blocked , The various management of users need to add interception operations , Only in this way can the security of the system be improved .
Login blocking
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (request.getSession().getAttribute("user") == null){
response.sendRedirect("/api");
return false;
}
return true;
}
}Resource release
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/api","/api/doLogin");
}
}4. To write Controller Front end controller code
First create a FileController class
① Jump to the page of file upload
// Jump to the page of file upload
@RequestMapping("/file-upload")
public String userList(){
return "file-upload";
}② Realize the function of file upload
@RequestMapping("/doAddForUser")
public String doAdd(User user, @RequestParam("file") MultipartFile files, HttpServletRequest request) throws IOException {
//String path = null;
if (files != null && !files.isEmpty()){
String name = UUID.randomUUID().toString().replace("-","");
// Get the extension of the file
String ext = FilenameUtils.getExtension(files.getOriginalFilename());
// Set the path of file upload
String url =request.getSession().getServletContext().getRealPath("/upload/");
File file = new File(url);
if (!file.exists()){
file.mkdir();
}
// Test path
System.out.println(request.getServletPath()+ "/upload");
System.out.println(request.getContextPath() + "/upload/");
// Save the renamed file in an absolute path
files.transferTo(new File(url+"/"+name+"."+ext));
user.setAvatar(request.getContextPath() + "/upload/"+name+"."+ext);
}
user.setId(UUID.randomUUID().toString());
String salt = PasswordUtils.getSalt();
String password = user.getPassword();
String encode = PasswordUtils.encode(password, salt);
user.setSalt(salt) ;
user.setPassword(encode);
user.setCreateTime(new Date());
userService.save(user);
return "redirect:/api/users";
}notes : How to upload multiple files? The changes are as follows :
③ Realize multi file upload function
In this project, the multi file upload function is not realized
private void commons(Object obj, @RequestParam("file") CommonsMultipartFile[] files, HttpServletRequest request) throws IOException {
//String path = null;
for (int i = 0; i < files.length; i++) {
if (files[i] != null && !files[i].isEmpty()){
String name = UUID.randomUUID().toString().replace("-","");
// Get the extension of the file
String ext = FilenameUtils.getExtension(files[i].getOriginalFilename());
// Set the path of file upload
String url =request.getSession().getServletContext().getRealPath("/upload/");
File file = new File(url);
if (!file.exists()){
file.mkdir();
}
// Test path
System.out.println(request.getServletPath()+ "/upload");
System.out.println(request.getContextPath() + "/upload/");
// Save the renamed file in an absolute path
files[i].transferTo(new File(url+"/"+name+"."+ext));
if (i == 0){
obj.setUrl1(request.getContextPath() + "/upload/"+name+"."+ext);
}
if (i == 1){
obj.setUrl2(request.getContextPath() + "/upload/"+name+"."+ext);
}
if (i == 2){
obj.setUrl3(request.getContextPath() + "/upload/"+name+"."+ext);
}
if (i == 3){
obj.setUrl4(request.getContextPath() + "/upload/"+name+"."+ext);
}
if (i == 4){
obj.setUrl5(request.getContextPath() + "/upload/"+name+"."+ext);
}
}
}
}5. Project optimization
For items where the front and rear ends are not separated , Most use page cache optimization , When the system suffers huge flow at a moment , When the first user accesses a page, the page data can be cached , such , Later, the pages visited by users are obtained from the cache , This reduces Operation on Database , Reduced the pressure on the database , So as to achieve optimal processing .
① Import dependence
<!--Redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--commons-pools2 Object pool dependency -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>② yaml To configure
## Redis To configure
redis:
# Server address
host: localhost
# port
port: 6379
# database
database: 0
# Timeout time
connect-timeout: 10000ms
lettuce:
pool:
# maximum connection
max-active: 8
# Maximum connection blocking wait time Default -1
max-wait: 10000ms
# Maximum free time Default 8
max-idle: 200
# Minimum free connection Default 8
min-idle: 5④ Redis Serialization
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
//key serialize
redisTemplate.setKeySerializer(new StringRedisSerializer());
//value serialize
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
//hash type key Serialization
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
//hash type value Serialization
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
}③ Optimize processing
@Autowired
private NewsService newsService;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private ThymeleafViewResolver viewResolver;
@RequestMapping(value = "/news",produces = "text/html;charset=utf-8")
@ResponseBody
public String roles(Model model, @RequestParam(value = "pageNo",defaultValue = "1")Integer pageNo
, @RequestParam(value = "pageSize",defaultValue = "10")Integer pageSize
, HttpServletRequest request, HttpServletResponse response){
//Redis Get page , If it's not empty , Then go back to the page
ValueOperations valueOperations = redisTemplate.opsForValue();
String html = (String) valueOperations.get("news-list");
if (!StringUtils.isEmpty(html)){
return html;
}
PageHelper.startPage(pageNo,pageSize);
List<News> list = newsService.list();
PageInfo<News> pageInfo = new PageInfo<>(list);
model.addAttribute("news",list);
model.addAttribute("pageInfo",pageInfo);
// If it is empty , Manual rendering , Deposit in Redis And in return
WebContext context = new WebContext(request, response, request.getServletContext(), request.getLocale(), model.asMap());
html = viewResolver.getTemplateEngine().process("news-list", context);
if (!StringUtils.isEmpty(html)){
// Set the expiration time for the cache
valueOperations.set("news-list",html,60, TimeUnit.SECONDS);
}
return html;
}④ Redis see

6. matters needing attention
Be careful @Controller and @RestController The difference between , This project uses the template to render the page , and @Controller Is used to respond to the page ; and @RestController It's used to return to Json
In the project optimization stage, you need to add notes on the method @ResponseBody, Because we cache the whole page , So convert the page into JSON For storage .

Inject Thymeleaf Parser , Will be specific The page is parsed into Json String to store


Will deposit Redis Data in plus expiration time , Because the data in the page should be consistent with the database , If the user sees the data tens of seconds or a minute ago, it is still barely acceptable .

At present, the code has been synchronized to Gitee:
https://gitee.com/gao-wumao/supplier
If necessary, go to the warehouse and pick it up by yourself , Please don't be stingy with the three companies in your hands !
source :https://blog.csdn.net/Gaowumao
recommend :
The most comprehensive java Interview question bank

PS: Because the official account platform changed the push rules. , If you don't want to miss the content , Remember to click after reading “ Looking at ”, Add one “ Star standard ”, In this way, each new article push will appear in your subscription list for the first time . spot “ Looking at ” Support us !
边栏推荐
- Player practice 11 audio resampling
- Unhandled exception stack overflow
- Recursive summary of learning function
- SystemC uses SC_ report_ Handler processing log printing
- Introduction to functions (inline functions and function overloading)
- Getting started alicloud haas510 open board DTU (version 2.0) --510-as
- C secret arts script Chapter 2 (detailed explanation of pointers) (Section 3)
- TestEngine with ID ‘junit-vintage‘ failed to discover tests
- PMP agile knowledge points
- Copy word content to excel and automatically divide it into multiple columns
猜你喜欢

C secret arts script Chapter 5 (paragraph) (Section 3)

Notepad common settings

QT multi thread drawing and real-time refreshing method

C語言中主函數調用另外一個函數,匯編代碼理解

SystemC common errors

Lua callinfo structure, stkid structure resolution

MobileOne: 移动端仅需1ms的高性能骨干,你值得拥有!

chrome://tracing Performance analysis artifact

Player actual combat 16 xdecode class

Socket model of punctual atom stm32f429 core board
随机推荐
Notepad common settings
JS (II) syntaxerror: cannot use import statement outside a module
Llvm pass-- virtual function protection
Basic usage of scanner
Create a slice slice pit using the make method
And, or, not equal, operator
Is Shell Scripting really a big technology?
工业机械臂(机器人)视觉定位引导系统
Huawei equipment is configured with H virtual private network
Leetcode 2176. 统计数组中相等且可以被整除的数对
Write policy of cache
Shell notes
Player actual combat 22 to solve the problems of flower screen and Caton
Analysis of lua source code
Running phase of SystemC
Detailed explanation of C language memset
C secret arts script Chapter 5 (paragraph) (Section 3)
2022版Redis数据删除策略
Player practice 18 xresample
[MySQL] basic database operation