当前位置:网站首页>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 !
边栏推荐
- Xshell (I) is missing mfc110u DLL file resolution
- Reverse analysis from x86 to x64tips
- [MySQL] basic database operation
- Three common methods of C language array initialization ({0}, memset, for loop assignment) and their principles
- How to realize the bidding strategy that pays more attention to transformation in the company's operation Google sem
- Notepad common settings
- En langage C, la fonction principale appelle une autre fonction et assemble le Code pour comprendre
- Unhandled exception stack overflow
- C secret script Chapter 1: data storage (in-depth analysis)
- QT database realizes page turning function
猜你喜欢

Notepad common settings

PMP agile knowledge points

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

Appnium (II) installation and basic use of mitmproxy

Reverse the encryption parameters of a hot water software

chapter19 Allocation

面向优化科学研究领域的软件包

Des File Encryptor based on MFC framework

Crack WinRAR to ad pop-up window

Player actual combat 22 to solve the problems of flower screen and Caton
随机推荐
Lua callinfo structure, stkid structure resolution
String concatenation and ternary operators
QA of some high frequency problems in oauth2 learning
[early knowledge of activities] list of recent activities of livevideostack
Analysis of lua source code
Conversion of player's actual 10 pixel format and size
New technology: efficient self-monitoring visual pre training, local occlusion no longer need to worry!
chapter19 Allocation
【活动早知道】LiveVideoStack近期活动一览
[OCR] aspriseocr C # English, number recognition (not Chinese)
Recursive summary of learning function
Unit test (I) unit test with JUnit
Shell脚本到底是什么高大上的技术吗?
For cross-border e-commerce, the bidding strategy focusing more on revenue - Google SEM
C secret arts script Chapter 2 (detailed explanation of pointers) (Section 3)
The original Xiaoyuan personal blog project that has been around for a month is open source (the blog has basic functions, including background management)
Perfect ending | detailed explanation of the implementation principle of go Distributed Link Tracking
Des File Encryptor based on MFC framework
ADB command (2) use monkey to test
2022版Redis数据删除策略