当前位置:网站首页>Tu oses le croire? Il m'a fallu deux jours pour développer un système de gestion.
Tu oses le croire? Il m'a fallu deux jours pour développer un système de gestion.
2022-06-12 14:30:00 【Java notes crevettes】
Cliquez sur le numéro public,UtilisationTemps partiel pour apprendre
Analyse des difficultés
Mais quand j'ai appris la nouvelle,C'est encore un choc à l'intérieur,Après tout, c'est un système de gestion complet,L'interface fonctionnelle ne doit pas être trop rudimentaire.Et tout, de la conception de la base de données à la livraison de l'ensemble du système, est fait seul,L'effet challenge est directement tiré!Mais calme - toi et réfléchis,Ce n'est pas très difficile non plus,Le processus global du projet est:Conception——>Documentation——>Codage——>Livraison.
Une fois le processus terminé,Commencez par une mise en œuvre étape par étape de rien,Je ne pensais pas qu'à la dernière étape,Il m'a fallu un jour et demi!!Il a fallu une demi - journée de plus pour optimiser l'ensemble du projet!
Examen du projet
Démonstration de l'effet final:

Sélection technique:
SpringBoot
Thymeleaf
Mybatis-Plus
MySQL
PageHelper
Lombok
Redis(Utilisation optimisée de la page post)
Introduction au processus opérationnel du projet
Module de connexion、Gestion du module utilisateur et attribution des rôles aux utilisateurs,Gestion du module des bulletins d'information、Module produit(Y compris les produits de base、Classification des marchandises、Ordre)Gestion、Gestion des modules de rôle; Si une ressource frontale a la permission d'utiliser cette ressource ,Utiliséthymeleaf Fonctions de base de la syntaxe des modèles pour l'identification des jugements et le téléchargement de fichiers .
Construction du projet(Utilisation du moteur Template)
1. Créer d'abordMavenProjets
Introduire les dépendances correspondantes, Construire le Répertoire de fichiers requis


2. CompilationyamlProfil
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 Configuration
thymeleaf:
# Fermer le cache
cache: false
prefix: classpath:/templates/
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml3. Construction de base au début du projet
Au début de la construction d'un projet , Pour rendre le système plus normalisé , J'ai l'habitude de configurer et de déclarer les bases à l'avance , Les technologies impliquées dans la conception d'un projet dès le début et certaines configurations de base pour ces technologies , Tout doit être planifié à l'avance (Habitudes personnelles).Par exemple,:Gestion des exceptions、Intercepteur、Filtre、 Classe constante, etc. .
①Gestion des exceptions
@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;
}
}② Intercepteur
L'intercepteur traite principalement de certaines ressources , Similaire à certaines ressources qui nécessitent la connexion de l'utilisateur , Certains ne sont pas nécessaires ,Par exemple,: La fonction login n'a pas besoin d'être bloquée , La gestion des utilisateurs nécessite l'ajout d'une opération d'interception , Afin d'améliorer la sécurité du système .
Interception de connexion
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;
}
}Libération des ressources
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/api","/api/doLogin");
}
}4. CompilationControllerCode du Contrôleur avant
Commencez par créer unFileControllerCatégorie
① Sautez à la page de téléchargement du fichier
// Sautez à la page de téléchargement du fichier
@RequestMapping("/file-upload")
public String userList(){
return "file-upload";
}② Réaliser la fonction de téléchargement de fichiers
@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("-","");
//Obtenir une extension de fichier
String ext = FilenameUtils.getExtension(files.getOriginalFilename());
// Définir le chemin de téléchargement du fichier
String url =request.getSession().getServletContext().getRealPath("/upload/");
File file = new File(url);
if (!file.exists()){
file.mkdir();
}
//Chemin d'essai
System.out.println(request.getServletPath()+ "/upload");
System.out.println(request.getContextPath() + "/upload/");
// Enregistrer le fichier renommé dans un chemin absolu
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";
}Note:: Comment réaliser le téléchargement de fichiers multiples :
③ Réaliser la fonction de téléchargement de fichiers multiples
La fonction de téléchargement de fichiers multiples n'est pas implémentée dans ce projet
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("-","");
//Obtenir une extension de fichier
String ext = FilenameUtils.getExtension(files[i].getOriginalFilename());
// Définir le chemin de téléchargement du fichier
String url =request.getSession().getServletContext().getRealPath("/upload/");
File file = new File(url);
if (!file.exists()){
file.mkdir();
}
//Chemin d'essai
System.out.println(request.getServletPath()+ "/upload");
System.out.println(request.getContextPath() + "/upload/");
// Enregistrer le fichier renommé dans un chemin absolu
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. Optimisation des projets
Pour les articles qui ne sont pas séparés de l'avant et de l'arrière , La plupart des optimisations de cache de page sont utilisées , Lorsque le système subit un flux important à un moment donné , Les données de la page peuvent être mises en cache lorsque le premier utilisateur accède à la page ,Voilà., Les pages visitées par les utilisateurs ultérieurs sont toutes extraites du cache ,Ça réduit Fonctionnement de la base de données,Réduction de la pression sur la base de données, Pour obtenir un traitement optimisé .
① Importer des dépendances
<!--Redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--commons-pools2 Dépendance du pool d'objets-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>② yamlConfiguration
## RedisConfiguration
redis:
# Adresse du serveur
host: localhost
# Port
port: 6379
# Base de données
database: 0
# Temps mort
connect-timeout: 10000ms
lettuce:
pool:
# Nombre maximum de connexions
max-active: 8
# Temps d'attente maximal de blocage de la connexion Par défaut -1
max-wait: 10000ms
# Temps libre maximum Par défaut8
max-idle: 200
# Connexion minimale libre Par défaut8
min-idle: 5④ RedisTraitement de sérialisation
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
//keySérialisation
redisTemplate.setKeySerializer(new StringRedisSerializer());
//valueSérialisation
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
//hashTypekeySérialisation de
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
//hashTypevalueSérialisation de
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
}③ Traitement optimisé
@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){
//RedisObtenir la page,Si ce n'est pas vide, Retourner directement à la 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);
//Si vide,Rendu manuel,DépôtRedisMilieu et retour
WebContext context = new WebContext(request, response, request.getServletContext(), request.getLocale(), model.asMap());
html = viewResolver.getTemplateEngine().process("news-list", context);
if (!StringUtils.isEmpty(html)){
//Définir un délai d'expiration pour le cache
valueOperations.set("news-list",html,60, TimeUnit.SECONDS);
}
return html;
}④ RedisVoir

6. Notes
Attention!@ControllerEt@RestControllerLa différence entre, Ce projet utilise une page de rendu de modèle ,Et@Controller C'est pour répondre à la page ;Et@RestControllerC'est pour revenir àJson
Annotation de la méthode requise pendant la phase d'optimisation du projet @ResponseBody, Parce que nous mettons en cache toute la page , Donc pour convertir la page en JSONStockage.

InjectionThymeleafAnalyseur,Sera spécifique La page est analysée en Json Chaîne à stocker


Sera déposé dansRedis Données en plus du temps d'expiration , Parce que les données de la page sont alignées sur la base de données , Si l'utilisateur voit des données il y a des dizaines de secondes ou une minute, c'est à peine acceptable. .

Le Code est actuellement synchronisé avec Gitee:
https://gitee.com/gao-wumao/supplier
Allez à l'entrepôt si nécessaire. , Et s'il vous plaît, Messieurs, ne soyez pas avares avec les trois ligues. !
Source::https://blog.csdn.net/Gaowumao
Recommandations:
Le plus completjavaQuestionnaire d'entrevue

PS:Parce que la plate - forme des numéros publics a changé les règles de poussée,Si vous ne voulez pas manquer le contenu,N'oubliez pas de lire un peu“Je regarde”,Ajouter“Étoile”,De cette façon, chaque fois qu'un nouvel article est poussé, il apparaîtra pour la première fois dans votre liste d'abonnements.Point“Je regarde”Soutenez - nous!
边栏推荐
猜你喜欢

Player practice 20 audio thread and video thread

Player practice 15 xdemux and avcodecparameters

通信流量分析

华为设备配置OSPF伪连接

QT multi thread drawing and real-time refreshing method

Notepad common settings

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

Communication flow analysis

In C language, the main function calls another function, which is understood by assembly code

Leetcode 2176. Count equal and divisible pairs in an array
随机推荐
And, or, not equal, operator
Player practice 18 xresample
面向优化科学研究领域的软件包
IAT hook hijacking process API call
Two months' experience in C language
C secret script Chapter 3 (detailed explanation of string function) (Section 1)
Dynamic search advertising intelligent search for matching keywords
Software package for optimization scientific research field
String concatenation and ternary operators
Unhandled exception stack overflow
MobileOne: 移动端仅需1ms的高性能骨干,你值得拥有!
QA of some high frequency problems in oauth2 learning
Visual studio common shortcuts
Postgresql14 installation and use tutorial
完美收官|详解 Go 分布式链路追踪实现原理
Copy word content to excel and automatically divide it into multiple columns
For cross-border e-commerce, the bidding strategy focusing more on revenue - Google SEM
Is Shell Scripting really a big technology?
Two methods of QT using threads
En langage C, la fonction principale appelle une autre fonction et assemble le Code pour comprendre