热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SSH框架网上商城项目第2战之基本增删查改、Service和Action的抽取

SSH框架网上商城项目第2战之基本增删查改、Service和Action的抽取,感兴趣的小伙伴们可以参考一下

上一节《SSH框架网上商城项目第1战之整合Struts2、Hibernate4.3和Spring4.2》我们搭建好了Struts2、Hibernate和Spring的开发环境,并成功将它们整合在一起。这节主要完成一些基本的增删改查以及Service、Dao和Action的抽取。
1. Service层的抽取
        上一节中,我们在service层简单写了save和update方法,这里我们开始完善该部分的代码,然后对service层的代码进行抽取。
1.1 完善CategoryService层
        对数据库的操作无非是增删改查,首先我们来完善CategoryService层的接口和实现:

//CategoryService接口 
public interface CategoryService extends BaseService { 
 
 public void save(Category category); //插入 
 
 public void update(Category category);//更新 
 
 public void delete(int id); //删除 
 
 public Category get(int id); //获取一个Category 
 
 public List query(); //获取全部Category 
 
} 

        对CategoryService接口的具体实现:

public class CategoryServiceImpl extends BaseServiceImpl implements CategoryService { 
 
 private SessionFactory sessionFactory; 
 
 //Spring会注进来 
 public void setSessionFactory(SessionFactory sessionFactory) { 
 this.sessiOnFactory= sessionFactory; 
 } 
 
 protected Session getSession() { 
 //从当前线程获取session,如果没有则创建一个新的session 
 return sessionFactory.getCurrentSession(); 
 } 
 
 @Override 
 public void save(Category category) { 
 getSession().save(category); 
 } 
 
 @Override 
 public void update(Category category) { 
 getSession().update(category); 
 } 
 
 @Override 
 public void delete(int id) { 
 /*第一种方法有个弊端,就是没删除一次得先查询一次 
 Object obj = getSession().get(Category.class, id); 
 if(obj != null) { 
  getSession().delete(obj); 
 }*/ 
 String hql = "delete Category while id=:id"; 
 getSession().createQuery(hql) // 
  .setInteger("id", id) // 
  .executeUpdate(); 
 } 
 
 @Override 
 public Category get(int id) { 
 return (Category) getSession().get(Category.class, id); 
 } 
 
 @Override 
 public List query() { 
 String hql = "from Category"; 
 return getSession().createQuery(hql).list(); 
 } 
} 

1.2 Service层抽取实现
完成了CategoryService后,我们来抽取Service层的基础实现。思路是这样的:我们抽取一个基础接口BaseService以及基础接口的实现BaseServiceImpl,后面开发的时候,如果需要新的Service,只需要做两步即可:首先定义一个新的接口xxxService继承BaseService接口,这个接口可以增加新的抽象方法;然后定义一个新的实现类xxxServiceImpl继承BaseServiceImpl并实现xxxService接口即可。这样更加便于项目的维护。
我们先根据上面的CategoryService接口来创建BaseService接口:

//基础接口BaseService,使用泛型 
public interface BaseService { 
 public void save(T t); 
 
 public void update(T t); 
 
 public void delete(int id); 
 
 public T get(int id); 
 
 public List query(); 
} 

然后再根据CategoryServiceImpl实现类创建BaseService接口的实现类BaseServiceImpl:

/** 
 * @Description TODO(公共模块的抽取) 
 * @author eson_15 
 * 
 */ 
@SuppressWarnings("unchecked") 
public class BaseServiceImpl implements BaseService { 
 
 private Class clazz; //clazz中存储了当前操作的类型,即泛型T 
 private SessionFactory sessionFactory; 
 
 public BaseServiceImpl() { 
  //下面三个打印信息可以去掉,这里是给自己看的 
  System.out.println("this代表的是当前调用构造方法的对象" + this); 
 System.out.println("获取当前this对象的父类信息" + this.getClass().getSuperclass()); 
 System.out.println("获取当前this对象的父类信息(包括泛型信息)" + this.getClass().getGenericSuperclass()); 
 //拿到泛型的参数类型 
 ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass(); 
 clazz = (Class)type.getActualTypeArguments()[0]; 
 } 
 
 public void setSessionFactory(SessionFactory sessionFactory) { 
 this.sessiOnFactory= sessionFactory; 
 } 
 
 protected Session getSession() { 
 //从当前线程获取session,如果没有则创建一个新的session 
 return sessionFactory.getCurrentSession(); 
 } 
 
 @Override 
 public void save(T t) { 
 getSession().save(t); 
 } 
 
 @Override 
 public void update(T t) { 
 getSession().update(t); 
 } 
 
 @Override 
 public void delete(int id) { 
 System.out.println(clazz.getSimpleName()); 
 String hql = "delete " + clazz.getSimpleName() + " as c where c.id=:id"; 
 getSession().createQuery(hql) // 
   .setInteger("id", id) // 
   .executeUpdate(); 
 } 
 
 @Override 
 public T get(int id) { 
 return (T) getSession().get(clazz, id); 
 } 
 
 @Override 
 public List query() { 
 String hql = "from " + clazz.getSimpleName(); 
 return getSession().createQuery(hql).list(); 
 } 
 
} 

抽取完了后,我们就可以改写CategoryService接口和CategoryServiceImpl实现类了。如下:

//CategoryService接口继承BaseService接口 
public interface CategoryService extends BaseService { 
 /* 
 * 只要添加CategoryService本身需要的新的方法即可,公共方法已经在BaseService中了 
 */ 
} 
 
/** 
 * @Description TODO(模块自身的业务逻辑) 
 * @author eson_15 
 * 
 */ 
public class CategoryServiceImpl extends BaseServiceImpl implements CategoryService { 
 
 /* 
 * 只需实现CategoryService接口中新增的方法即可,公共方法已经在BaseServiceImpl中实现了 
 */ 
} 

        从代码中可以看出,新增的Service只需要继承BaseService接口,然后在接口中新增本Service所需要的业务逻辑即可。新增的ServiceImpl只需要继承BaseServiceImpl并实现新增的业务逻辑即可。
        但是别忘了很重要的一点:就是修改Spring的配置文件beans.xml中的bean

 
 
  
 
 
 

        将原来categoryService中的property干掉,然后增加parent属性,指明继承baseService;然后配置一下baseService,将sessionFactory配到baseService中去,另外要注意一点:设置lazy-init属性为true,因为baseService是泛型类,泛型类是不能实例化的。至此,Service层的抽取就搞定了。

2. Service层添加一个Account
        刚刚抽取好了Service层,那么现在我们想写一个Account(管理员)的service就很简单了:
        首先写一个AccountService接口继承BaseService:

public interface AccountService extends BaseService { //注意BaseService里的泛型现在是Account 
 /* 
 * 只要添加AccountService本身需要的新的方法即可,公共方法已经在BaseService中了 
 */ 
} 

        然后写一个AccountServiceImpl实现类继承BaseServiceImpl实现类,并实现AccountService接口即可:

public class AccountServiceImpl extends BaseServiceImpl implements AccountService { 
 
 /* 
 * 只需实现AccountService接口中新增的方法即可,公共方法已经在BaseServiceImpl中实现了 
 */ 
 
 //管理登陆功能,后期再完善 
} 

        最后在beans.xml文件里加上如下配置:
  
        这样就写好了一个新的service了,以后需要添加service就遵循这个流程,非常方便。
3. Action的抽取
3.1 Action中往域(request,session,application等)中存数据
        我们知道,在Action中可以直接通过ActionContext.getContext()去获取一个ActionContext对象,然后通过该对象再去获得相应的域对象;也可以通过实现xxxAware接口来注入相应的域对象。我们先来看一下这两种方法:

public class CategoryAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{ 
 
 private Category category; 
 
 private CategoryService categoryService; 
 
 public void setCategoryService(CategoryService categoryService) { 
  this.categoryService = categoryService; 
 } 
 
 public String update() { 
 System.out.println("----update----"); 
 categoryService.update(category); 
 return "index"; 
 } 
 
 public String save() { 
 System.out.println("----save----"); 
 return "index"; 
 } 
 
 public String query() { 
  //解决方案一,采用相应的map取代原来的内置对象,这样与jsp没有依赖,但是代码量比较大 
 // ActionContext.getContext().put("categoryList", categoryService.query()); //放到request域中 
 // ActionContext.getContext().getSession().put("categoryList", categoryService.query()); //放到session域中 
 // ActionContext.getContext().getApplication().put("categoryList", categoryService.query()); //放到application域中 
  
 //解决方案二,实现相应的接口(RequestAware,SessionAware,ApplicationAware),让相应的map注入 
 request.put("categoryList", categoryService.query()); 
 session.put("categoryList", categoryService.query()); 
 application.put("categoryList", categoryService.query()); 
 return "index"; 
 } 
 
 public Category getCategory() { 
 return category; 
 } 
 
 public void setCategory(Category category) { 
 this.category = category; 
 } 
 
 private Map request; 
 private Map session; 
 private Map application; 
 
 @Override 
 public void setApplication(Map application) { 
 this.application = application; 
 } 
 
 @Override 
 public void setSession(Map session) { 
 this.session = session; 
 } 
 
 @Override 
 public void setRequest(Map request) { 
 this.request = request; 
 } 
} 

还是上一节整合三大框架时的CategoryAction类,我们在里面加了一个query方法,在该方法中,我们通过向request域、session域和application域中存入查询的结果。第一种方法是直接使用ActionContext来实现,不需要实现任何接口,但是代码量较大;第二种方法通过实现RequestAware、SessionAware和ApplicationAware接口,实现该接口的三个抽象方法把request、session和application注入进来,然后赋给相应的成员变量中,这样就可以在query方法中向域中存放查询结果了。这代码量貌似比第一种方法更大……但是我们可以抽取,先往下看。
我们在index.jsp中新加一个查询连接来测试能否将查询结果显示出来:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 
 
 
  
  
  
 
  
 访问update 
 访问save 
 查询所有类别
${category.id } | ${category.type } | ${category.hot }
${category.id } | ${category.type } | ${category.hot }
${category.id } | ${category.type } | ${category.hot }

3.2 抽取BaseAction
        刚刚提到了,第二种方法的代码量更大,但是我们可以抽取一个BaseAction,专门处理这些域相关的操作。

public class BaseAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware { 
 
 protected Map request; 
 protected Map session; 
 protected Map application; 
 
 @Override 
 public void setApplication(Map application) { 
 this.application = application; 
 } 
 
 @Override 
 public void setSession(Map session) { 
 this.session = session; 
 } 
 
 @Override 
 public void setRequest(Map request) { 
 this.request = request; 
 } 
} 

        然后我们自己的Action如果需要用到这些域对象来存储数据时,直接继承BaseAction即可,就能直接使用request、session和application对象了。所以修改后的CategoryAction如下:

public class CategoryAction extends BaseAction { 
 
 private Category category; 
 
 private CategoryService categoryService; 
 
 public void setCategoryService(CategoryService categoryService) { 
  this.categoryService = categoryService; 
 } 
public String update() {System.out.println("----update----");categoryService.update(category); return "index"; }public String save() {System.out.println("----save----");return "index"; } public String query() {request.put("categoryList", categoryService.query()); session.put("categoryList", categoryService.query()); application.put("categoryList", categoryService.query()); return "index"; } public Category getCategory() { return category; } public void setCategory(Category category) {this.category = category; }}

        后面所有要使用request、session和application域的Action,只要直接继承BaseAction即可,非常方便。
3.3 获取参数(ModelDriven)
        我们继续看上面的CategoryAction类,里面有个成员变量category,这是个POJO,定义这个变量并写好set和get方法是为了JSP页面可以通过url后面附带参数传进来,参数是category对象中的属性,比如id,type等,但是url中的参数必须写成category.id、category.type等。这样struts会自动将这写参数注入到category对象中,然后我们就可以直接使用这个category对象了,但是这样有点繁琐。我们可以使用ModelDriven来更方便的解决。

public class CategoryAction extends BaseAction implements ModelDriven{ 
 
 private Category category; 
 
 //使用ModelDriven接口必须要实现getModel()方法,此方法会把返回的项压到栈顶 
 @Override 
 public Category getModel() { 
 category = new Category(); 
 return category; 
 } 
 private CategoryService categoryService; 
 
 public void setCategoryService(CategoryService categoryService) { 
  this.categoryService = categoryService; 
 } 
 
 public String update() { 
 System.out.println("----update----"); 
 categoryService.update(category); 
 return "index"; 
 } 
 
 public String save() { 
 System.out.println("----save----"); 
 return "index"; 
 } 
 
 public String query() { 
 request.put("categoryList", categoryService.query()); 
 session.put("categoryList", categoryService.query()); 
 application.put("categoryList", categoryService.query()); 
 return "index"; 
 } 
 
} 

这样我们在前台JSP页面就不用带category.id这种繁琐的参数了,看JSP页面中的ModelDriven部分:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 
 
 
  
  
  
 
  
 访问update 
 测试ModelDriven 
 查询所有类别
${category.id } | ${category.type } | ${category.hot }
${category.id } | ${category.type } | ${category.hot }
${category.id } | ${category.type } | ${category.hot }

        测试结果是可以获得catgory,并且将id,type和hot属性全部赋值好。我们可以看出,通过实现ModelDriven接口,我们可以很方便的在url中携带参数,Action中只需要实现getModel方法,new一个要使用的对象返回即可。到这里我们很容易想到,struts中肯定会有很多这种model需要获取,所以这一块我们也要抽取到BaseAction中去。
3.4 抽取ModelDriven到BaseAction
        首先我们在BaseAction中添加ModelDriven部分的代码,如下:

//因为有很多不同的model都需要使用ModelDriven,所以这里使用泛型 
public class BaseAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware,ModelDriven { 
 
 protected Map request; 
 protected Map session; 
 protected Map application; 
 
 protected T model; 
 
 @Override 
 public void setApplication(Map application) { 
 this.application = application; 
 } 
 
 @Override 
 public void setSession(Map session) { 
 this.session = session; 
 } 
 
 @Override 
 public void setRequest(Map request) { 
 this.request = request; 
 } 
 
 @Override 
 public T getModel() { //这里通过解析传进来的T来new一个对应的instance 
 ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass(); 
 Class clazz = (Class)type.getActualTypeArguments()[0]; 
 try { 
  model = (T)clazz.newInstance(); 
 } catch (Exception e) { 
  throw new RuntimeException(e); 
 } 
 return model; 
 } 
} 

抽取完了后,CategoryAction中的代码会越来越少:

//继承BaseAction,并且加上泛型 
public class CategoryAction extends BaseAction { 
 
 private CategoryService categoryService; 
 
 public void setCategoryService(CategoryService categoryService) { 
 this.categoryService = categoryService; 
 } 
 
 public String update() { 
 System.out.println("----update----"); 
 categoryService.update(model);//直接使用model 
 return "index"; 
 } 
 
 public String save() { 
 System.out.println("----save----"); 
 System.out.println(model); //直接使用model 
 return "index"; 
 } 
 
 public String query() { 
 request.put("categoryList", categoryService.query()); 
 session.put("categoryList", categoryService.query()); 
 application.put("categoryList", categoryService.query()); 
 return "index"; 
 } 
 
} 

        到这里,还有一个看着不爽的地方,就是categoryService这个成员变量,它一直存在在CategoryAction里,因为CategoryAction中有用到categoryService对象中的方法,所以必须得创建这个对象,并且有set方法才能注入进来。这就导致一个弊端:如果很多Action都需要使用categoryService的话,那就必须在它们的Action里创建这个对象和set方法,而且,如果一个Action中要使用好几个不同的service对象,那就得全部创建,这样就变得很冗杂。
3.5 抽取service到BaseAction
        针对上面的问题,我们将工程中所有的service对象都抽取到BaseAction中创建,这样其他Action继承BaseAction后,想用什么service就直接拿来用即可:

//我将BaseAction中的内容归归类了 
public class BaseAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware,ModelDriven { 
 
 //service对象 
 protected CategoryService categoryService; 
 protected AccountService accountService; 
 
 public void setCategoryService(CategoryService categoryService) { 
 this.categoryService = categoryService; 
 } 
 public void setAccountService(AccountService accountService) { 
 this.accountService = accountService; 
 } 
 
 //域对象 
 protected Map request; 
 protected Map session; 
 protected Map application; 
  
 @Override 
 public void setApplication(Map application) { 
 this.application = application; 
 } 
 @Override 
 public void setSession(Map session) { 
 this.session = session; 
 } 
 @Override 
 public void setRequest(Map request) { 
 this.request = request; 
 } 
 
 //ModelDriven 
 protected T model; 
 @Override 
 public T getModel() { 
 ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass(); 
 Class clazz = (Class)type.getActualTypeArguments()[0]; 
 try { 
  model = (T)clazz.newInstance(); 
 } catch (Exception e) { 
  throw new RuntimeException(e); 
 } 
 return model; 
 } 
} 
 这样CategoryAction中就更加清爽了:
public class CategoryAction extends BaseAction { 
 
 public String update() { 
 System.out.println("----update----"); 
 categoryService.update(model); 
 return "index"; 
 } 
 
 public String save() { 
 System.out.println("----save----"); 
 System.out.println(model); 
 return "index"; 
 } 
 
 public String query() { 
 request.put("categoryList", categoryService.query()); 
 session.put("categoryList", categoryService.query()); 
 application.put("categoryList", categoryService.query()); 
 return "index"; 
 } 
 
} 

        有人可能会问,BaseAction中注入了那么多service对象的话不会冗余么?这是不会的,因为就算不写在BaseAction中,Spring容器也是会创建这个对象的,这点没有关系,相反,service对象全放在BaseAction中更加便于其他Action的开发,而且BaseAction不需要配到struts.xml文件中,因为根本就没有哪个JSP会请求BaseAction,它只是让其他Action来继承用的。
        还有一点别忘了:那就是修改在beans.xml中的配置:

 
 
  
  
 
 

         新加一个baseAction的bean,将工程中所有service对象作为property配好,将原来的categoryAction中的property干掉。
        以后我们如果要写新的xxxAction,直接继承BaseAction即可,如果xxxAction中有用到某个service,直接拿来用即可,只需要在beans.xml文件中加一个xxxAction对应的bean,在struts.xml文件中配置好跳转即可。

4. 将xml改成注解
        我们可以看到,随着项目越写越大,beans.xml中的配置会越来越多,而且很多配置有冗余,为了更加便于开发,我们现在将xml的配置改成注解的形式,我们先看一下beans.xml中的配置:

        这些是我们之前搭建环境以及抽取的时候写的bean,这些都需要转换成注解的形式,下面我们一块一块的换掉:首先替换service部分,这部分有三个:baseService、categoryService和accountService。替换如下:


        然后将beans.xml中的相应部分干掉即可。接下来修改ActIon部分,主要有baseAction、categoryAction和accountAction三个,替换如下:


        然后再干掉beans.xml中的Action部分的配置即可,最后在beans.xml文件中添加一个如下配置,就可以使用注解了。
 
        有人可能会问,为什么service和action两个使用注解的时候不一样呢?service中使用的是@Service而action中使用的是@Controller呢?其实是一样的,只是为了区分它们是不同层的bean而已,便于阅读。

整个项目的源码下载地址:https://www.jb51.net/article/86099.htm

原文地址:http://blog.csdn.net/eson_15/article/details/51297698

以上就是SSH框架网上商城项目第2战的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文介绍了互联网思维中的三个段子,涵盖了餐饮行业、淘品牌和创业企业的案例。通过这些案例,探讨了互联网思维的九大分类和十九条法则。其中包括雕爷牛腩餐厅的成功经验,三只松鼠淘品牌的包装策略以及一家创业企业的销售额增长情况。这些案例展示了互联网思维在不同领域的应用和成功之道。 ... [详细]
  • 本文详细介绍了在Centos7上部署安装zabbix5.0的步骤和注意事项,包括准备工作、获取所需的yum源、关闭防火墙和SELINUX等。提供了一步一步的操作指南,帮助读者顺利完成安装过程。 ... [详细]
author-avatar
卡吉米国际早教_763
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有