• 商城03——完成商品添加功能


    1.   课程计划

    完成商品添加功能

    1、商品类目选择

    2、图片上传

    3、图片服务器搭建

    4、kindEditor富文本编辑器的使用

    5、商品添加功能

    2.   实现商品类目选择功能

    2.1. 需求

    在商品添加页面,点击“选择类目”显示商品类目列表:

    使用easyUI的异步tree控件来完成。

    异步tree的行为

      树控件读取URL。子节点的加载依赖于父节点的状态。当展开一个封闭的节点,如果节点没有加载子节点,它将会把节点id的值作为http请求参数并命名为‘id’,通过URL发送到服务器上面检索子节点。

    异步tree的数据结构

    • id:节点id
    • text:节点名称
    • state:如果不是叶子节点就是closed,叶子节点就是open。close的节点点击后会在此发送请求查询子项目。

    {

      "id":1,

      "text":"Node1",

      "state":"closed"     //如果节点为父节点则状态为“closed”,如果是叶子节点“open”

    }

    2.2.数据库

    表中的数据为树形结构,可以满足要求

    2.3 功能分析

     index.jsp:新增商品--->item-add.jsp

     

    item-add.jsp: 选择类目--->selectItemCat

    selectItemCat在common.js中实现   请求初始化树形控件的url:/item/cast/list

     

    点击父节点,请求初始化子节点动作是tree空间封装好的,每打开一个父节点做一次ajax请求

    请求参数:id:当前节点的id。根据此id查询子节点

    返回结果:一个json数据,是一个列表:

    [

    {

      "id":1,

      "text":"Node1",

      "state":"closed"     //如果节点为父节点则状态为“closed”,如果是叶子节点“open”

    },

    {

      "id":2,

      "text":"Node2",

      "state":"closed"     //如果节点为父节点则状态为“closed”,如果是叶子节点“open”

    }

    ]

    2.4. DAO层

      select * from tb_item_cat where parent_id=2

      使用逆向工程生成的mapper文件:TbItemCatMapper.java、TbItemCatMapper.xml

    2.5. Service层

      功能:接收parentid参数,根据parentid查询子类目类别。返回一个分类列表。可以创建一个pojo来描述一个节点的格式,返回一个pojo列表。

      创建一个pojo:

        包含id,text,state属性。因为其他工程也可能用到此pojo,所以应放在taotao-common中:

    public class EasyUITreeNode implements Serializable {
        private Long id;  //节点id
        private String text; //节点名称
        private String state; //如果不是叶子节点就是close,叶子节点就是open
        set/get。。。。。
    }

    public interface ItemCatService {
        public List<TbItemCat> getItemCatList(Long parentId);
    }

    @Service
    public class ItemCatServiceImpl implements ItemCatService {
    
        @Autowired
        private TbItemCatMapper itemCatMapper;
        
        @Override
        public List<EasyUITreeNode> getItemCatList(Long parentId) {
            //创建查询条件
            TbItemCatExample example = new TbItemCatExample();
            Criteria criteria = example.createCriteria();
            //根据parentid查询子节点
            criteria.andParentIdEqualTo(parentId);
            List<TbItemCat> list = itemCatMapper.selectByExample(example);
            //把列表转换成treeNodeList
            List<EasyUITreeNode> resultList = new ArrayList<EasyUITreeNode>();
            for(TbItemCat tbItemCat:list){
                EasyUITreeNode node = new EasyUITreeNode();
                node.setId(tbItemCat.getId());
                node.setText(tbItemCat.getName());
                node.setState(tbItemCat.getIsParent()?"closed":"open");
                resultList.add(node);
            }
            //返回结果
            return resultList;
        }
    }

    2.6 Controller层

     功能:接收页面请求的参数,名为id。调用service查询分类列表。返回json格式是列表。需要使用@ResponseBody注解。

     

    @Controller
    @RequestMapping("/item/cat")
    public class ItemCatController {
    
        @Autowired
        private ItemCatService itemCatService;
        
        @RequestMapping("/list")
        @ResponseBody
        public List<EasyUITreeNode> getItemCatList(@RequestParam(value="id",defaultValue="0")Long parentId){
            List<EasyUITreeNode> list = itemCatService.getItemCatList(parentId);
            return list;
        }
    }

    3.实现上传图片功能

    首先安装nginx来提供http服务。过程略。

    FastDFS只是解决了图片保存问题,要通过http访问图片 必须安装nginx。

    3.1 分布式文件服务器FastDFS

    3.1.1 什么是FastDFS

      FastDFS 是用 c 语言编写的一款开源的分布式文件系统。FastDFS 为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用 FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。

      FastDFS 架构包括 Tracker server 和 Storage server。客户端请求 Tracker server 进行文件上传、下载,通过 Tracker server 调度最终由 Storage server 完成文件上传和下载。

      Tracker server 作用是负载均衡和调度,通过 Tracker server 在文件上传时可以根据一些策略找到 Storage server 提供文件上传服务。可以将 tracker 称为追踪服务器或调度服务器。

      Storage server 作用是文件存储,客户端上传的文件最终存储在 Storage 服务器上,Storageserver 没有实现自己的文件系统而是利用操作系统 的文件系统来管理文件。可以将storage称为存储服务器。

    服务端两个角色:

    Tracker:管理集群,tracker 也可以实现集群。每个 tracker 节点地位平等。收集 Storage 集群的状态。

    Storage:实际保存文件   Storage 分为多个组,每个组之间保存的文件是不同的。每个组内部可以有多个成员,组成员内部保存的内容是一样的,组成员的地位是一致的,没有主从的概念。

    3.1.2 文件上传及下载的流程

    (1) 文件上传流程

     

      客户端上传文件后存储服务器将文件 ID 返回给客户端,此文件 ID 用于以后访问该文件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名。

      

       组名:文件上传后所在的 storage 组名称,在文件上传成功后有 storage 服务器返回,需要客户端自行保存。

      虚拟磁盘路径:storage 配置的虚拟路径,与磁盘选项 store_path*对应。如果配置了store_path0 则是 M00,如果配置了 store_path1 则是 M01,以此类推。

      数据两级目录:storage 服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据文件。

      文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储服务器 IP 地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。

    (2) 文件下载流程

     

    3.1.3 最简单的 FastDFS 架构

     

    3.1.4 FastDFS安装

      略,自己安装的FastDFS的IP地址固定为192.168.25.133

    3.1.5 FastDFS实现图片上传小测试

    这里我们在taotao-manager-web工程下做测试,在其下的的 src/test/java 下建一个测试类FastDfsTest。

    (1)首先在pom.xml引入fastdfs的依赖:

    <dependency>
                <groupId>org.csource.fastdfs</groupId>
                <artifactId>fastdfs</artifactId>
                <version>1.2</version>
            </dependency>
    View Code

    (2)在 src/main/resources 的resource 文件夹下建一个资源文件fastdfs.conf,里面内容为trackServer的IP地址与端口号:

      tracker_server=192.168.25.133:22122

    (3)FastDfsTest:

    public class FastDfsTest {
    
        @Test
        public void testUplode() throws Exception{
            //创建一个配置文件,文件名任意,内容就是tracker服务器的地址。在fastdfs.conf中已配置,名称为tracker_server
            //1.加载配置文件。(这时我们就知道tracker在什么地方了)
            ClientGlobal.init("D:/Workspaces/MyEclipse 2015/taotao-manager-web/src/main/resources/resource/fastdfs.conf");
            //2.构建一个管理者客户端TrackerClient
            TrackerClient trackerClient = new TrackerClient();
            //3.连接管理者服务端
            TrackerServer trackerServer = trackerClient.getConnection();
            //4.声明存储服务端StorageServer
            StorageServer storageServer = null;
            //5.获取存储服务端的客户端对象
            StorageClient storageClient = new StorageClient(trackerServer, storageServer);
            //6.上传文件
            String[] strings = storageClient.upload_file("F:/pictures/1.jpg", "jpg", null);
            for (String string : strings) {
                System.out.println(string);
            }
        }
    }

    输出结果
    
    

     group1
     M00/00/00/wKgZhV0A-POAUmyRAAE0WLGwjmM340.jpg

    测试:网页输入http://192.168.25.133/group1/M00/00/00/wKgZhV0A-POAUmyRAAE0WLGwjmM340.jpg便得到了要显示的图片:

    3.1.6 使用FastDFSClient工具类实现图片上传功能

    将 fastDFS 上传文件封装到一个工具类FastDFSClient中,放到taotao-manager-common工程下的util包下,注意引入fastDFS依赖。

    package com.taotao.common.util;
    
    import org.csource.common.NameValuePair;
    import org.csource.fastdfs.ClientGlobal;
    import org.csource.fastdfs.StorageClient1;
    import org.csource.fastdfs.StorageServer;
    import org.csource.fastdfs.TrackerClient;
    import org.csource.fastdfs.TrackerServer;
    
    public class FastDFSClient {
    
        private TrackerClient trackerClient = null;
        private TrackerServer trackerServer = null;
        private StorageServer storageServer = null;
        private StorageClient1 storageClient = null;
        
        public FastDFSClient(String conf) throws Exception {
            if (conf.contains("classpath:")) {
                conf = conf.replace("classpath:", this.getClass().getResource("/").getPath());
            }
            ClientGlobal.init(conf);
            trackerClient = new TrackerClient();
            trackerServer = trackerClient.getConnection();
            storageServer = null;
            storageClient = new StorageClient1(trackerServer, storageServer);
        }
        
        /**
         * 上传文件方法
         * @param fileName 文件全路径
         * @param extName 文件扩展名,不包含(.)
         * @param metas 文件扩展信息
         * @return
         * @throws Exception
         */
        public String uploadFile(String fileName, String extName, NameValuePair[] metas) throws Exception {
            String result = storageClient.upload_file1(fileName, extName, metas);
            return result;
        }
        
        public String uploadFile(String fileName) throws Exception {
            return uploadFile(fileName, null, null);
        }
        
        public String uploadFile(String fileName, String extName) throws Exception {
            return uploadFile(fileName, extName, null);
        }
        
        /**
         * 上传文件方法
         * @param fileContent 文件的内容,字节数组
         * @param extName 文件扩展名
         * @param metas 文件扩展信息
         * @return
         * @throws Exception
         */
        public String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas) throws Exception {
            
            String result = storageClient.upload_file1(fileContent, extName, metas);
            return result;
        }
        
        public String uploadFile(byte[] fileContent) throws Exception {
            return uploadFile(fileContent, null, null);
        }
        
        public String uploadFile(byte[] fileContent, String extName) throws Exception {
            return uploadFile(fileContent, extName, null);
        }
    }
    View Code

    测试:

    @Test
        public void testFastDfsClient() throws Exception {
            FastDFSClient fastDFSClient = new FastDFSClient("D:/Workspaces/MyEclipse 2015/taotao-manager-web/src/main/resources/resource/fastdfs.conf");
            String string = fastDFSClient.uploadFile("F:/pictures/2.jpg", "jpg");
                System.out.println(string);
        }

    输出结果:
    group1/M00/00/00/wKgZhV0BAaiAYtIxAAHlC6LIRGI190.jpg

    3.2 实现图片上传

    前端:

    item-add:上传图片--->picFileUpload

    common.js: initPicUpload --->kingEditorParams

    kingEditorParams:

    使用的是KindEditor的多图片上传插件。

    KindEditor4.x文档:http://kindeditor.net/doc.php

    请求的url:/pic/upload

    参数:MultiParFile uploadFile

    返回值:(json数据)

    可以创建一个pojo对应返回值,也可以使用map。

    图片上传功能在taotao-manager-web(控制层)实现:

    3.2.1 配置文件

    (1)在pinyougou-shop-web工程springmvc.xml配置文件上传解析器:

    <!-- 配置多媒体解析器(文件上传解析器) -->
        <bean id="multipartResolver"
            class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <property name="defaultEncoding" value="UTF-8"></property>
            <!-- 设定文件上传的最大值5MB,5*1024*1024 -->
            <property name="maxUploadSize" value="5242880"></property>
        </bean>

    (2)在 src/main/resources 的resource 文件夹下建一个资源文件resource.properties,里面内容为 图片服务器 的地址:

        TAOTAO_IMAGE_SERVER_URL=http://192.168.25.133/

      然后在springmvc.xml中加载该配置文件:   (之后在Controller中加@value("${...}")取值)

      <!-- 加载配置文件 -->
        <context:property-placeholder location="classpath:resource/resource.properties" />

    3.2.2 Controller层:

    @Controller
    public class PictureController {
        
        @Value("${TAOTAO_IMAGE_SERVER_URL}")
        private String TAOTAO_IMAGE_SERVER_URL;
        
        
        @RequestMapping("/pic/upload")
        @ResponseBody
        public Map uploadFile(MultipartFile uploadFile) {
            try {
                //1.创建一个 FastDFS 的客户端
                FastDFSClient fastDFSClient = new FastDFSClient("classpath:resource/fastdfs.conf");
                //取文件扩展名
                String originalFilename = uploadFile.getOriginalFilename();
                String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
                //执行上传处理
                String url = fastDFSClient.uploadFile(uploadFile.getBytes(), extName);
                
                //拼接返回的 url和 ip 地址,拼装成完整的 url
                url = TAOTAO_IMAGE_SERVER_URL + url;
                //封装到map中返回
                Map result = new HashMap<>();
                result.put("error", 0);
                result.put("url", url);
                return result;
                
            } catch (Exception e) {
                e.printStackTrace();
                Map result = new HashMap<>();
                result.put("error", 1);
                result.put("message", "图片上传失败");
                return result;
            }    
        }
    }

     这里在谷歌浏览器上传失败了!是因为浏览兼容性问题

    3.2.3 解决浏览器兼容性问题

    使Controller层返回String类型

    @Response 直接响应浏览器,不走逻辑视图,相当于调用response对象调用read方法,往浏览器写内容。如果返回值是对象,它会默认将对象变为json再响应。如果直接返回字符串Sting,它就不转换了,因为浏览器可以识别字符串。

    为了解决浏览器兼容问题,我们不再返回Map,而是返回String,需要将原来封装到Map的信息手工转为json(把java对象变为json串),再转为String。

    JsonUtils实现把java对象变为json串,放在taotao-manager-common的util包下

    import java.util.List;
    
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.JavaType;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class JsonUtils {
    
        // 定义jackson对象
        private static final ObjectMapper MAPPER = new ObjectMapper();
    
        /**
         * 将对象转换成json字符串。
         * <p>Title: pojoToJson</p>
         * <p>Description: </p>
         * @param data
         * @return
         */
        public static String objectToJson(Object data) {
            try {
                String string = MAPPER.writeValueAsString(data);
                return string;
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            return null;
        }
        
        /**
         * 将json结果集转化为对象
         * 
         * @param jsonData json数据
         * @param clazz 对象中的object类型
         * @return
         */
        public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
            try {
                T t = MAPPER.readValue(jsonData, beanType);
                return t;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
        
        /**
         * 将json数据转换成pojo对象list
         * <p>Title: jsonToList</p>
         * <p>Description: </p>
         * @param jsonData
         * @param beanType
         * @return
         */
        public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) {
            JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
            try {
                List<T> list = MAPPER.readValue(jsonData, javaType);
                return list;
            } catch (Exception e) {
                e.printStackTrace();
            }
            
            return null;
        }
        
    }
    View Code

    调用其objectToJson()方法即可实现。

    Controller层代码改为:

    @Controller
    public class PictureController {
        
        @Value("${TAOTAO_IMAGE_SERVER_URL}")
        private String TAOTAO_IMAGE_SERVER_URL;
        
        
        @RequestMapping("/pic/upload")
        @ResponseBody
        public String uploadFile(MultipartFile uploadFile) {
            try {
                //1.创建一个 FastDFS 的客户端
                FastDFSClient fastDFSClient = new FastDFSClient("classpath:resource/fastdfs.conf");
                //取文件扩展名
                String originalFilename = uploadFile.getOriginalFilename();
                String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
                //执行上传处理
                String url = fastDFSClient.uploadFile(uploadFile.getBytes(), extName);
                
                //拼接返回的 url和 ip 地址,拼装成完整的 url
                url = TAOTAO_IMAGE_SERVER_URL + url;
                //封装到map中返回
                Map result = new HashMap<>();
                result.put("error", 0);
                result.put("url", url);
                return JsonUtils.objectToJson(result);
                
            } catch (Exception e) {
                e.printStackTrace();
                Map result = new HashMap<>();
                result.put("error", 1);
                result.put("message", "图片上传失败");
                return JsonUtils.objectToJson(result);
            }    
        }
    }

    这里我点击上传失败:

    报错信息:

    java.io.FileNotFoundException: D:WorkspacesMyEclipse%202015 aotao-manager-web argetclasses esourcefastdfs.conf (系统找不到指定的路径。)

    不明白为什么路径会不对,FastDFSClient(String conf)是这样定义的:

    public FastDFSClient(String conf) throws Exception {
            if (conf.contains("classpath:")) {
                conf = conf.replace("classpath:", this.getClass().getResource("/").getPath());
            }
            ClientGlobal.init(conf);
            trackerClient = new TrackerClient();
            trackerServer = trackerClient.getConnection();
            storageServer = null;
            storageClient = new StorageClient1(trackerServer, storageServer);
        }

    这里claspath:识别的路径和fastdfs.conf所在路径不符。然后我改成全路径就对了。。。问题还有待解决。。。

    FastDFSClient fastDFSClient = new FastDFSClient("D:/Workspaces/MyEclipse 2015/taotao-manager-web/src/main/resources/resource/fastdfs.conf");

     上传成功:

     

     4.富文本编辑器

     

    纯js实现,略。

    5.提交表单,完成商品添加功能

     

    前端:

    itme-add.jsp:提交--->submitForm()

    submitForm():

     

    1) url:/item/save 

    2)要响应一个json数据,包含status属性。这里我们封装一个类TaotaoResult(自定义响应类),放在taotao-manager-common的util包下:

    • private Integer status; // 响应业务状态
    • private String msg; // 响应消息
    • private Object data; // 响应中的数据
    package com.taotao.common.util;
    
    import java.io.Serializable;
    import java.util.List;
    
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    /**
     * 淘淘商城自定义响应结构
     */
    public class TaotaoResult implements Serializable{
    
        // 定义jackson对象
        private static final ObjectMapper MAPPER = new ObjectMapper();
    
        // 响应业务状态
        private Integer status;
    
        // 响应消息
        private String msg;
    
        // 响应中的数据
        private Object data;
    
        public static TaotaoResult build(Integer status, String msg, Object data) {
            return new TaotaoResult(status, msg, data);
        }
    
        public static TaotaoResult ok(Object data) {
            return new TaotaoResult(data);
        }
    
        public static TaotaoResult ok() {
            return new TaotaoResult(null);
        }
    
        public TaotaoResult() {
    
        }
    
        public static TaotaoResult build(Integer status, String msg) {
            return new TaotaoResult(status, msg, null);
        }
    
        public TaotaoResult(Integer status, String msg, Object data) {
            this.status = status;
            this.msg = msg;
            this.data = data;
        }
    
        public TaotaoResult(Object data) {
            this.status = 200;
            this.msg = "OK";
            this.data = data;
        }
    
    //    public Boolean isOK() {
    //        return this.status == 200;
    //    }
    
        public Integer getStatus() {
            return status;
        }
    
        public void setStatus(Integer status) {
            this.status = status;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        public Object getData() {
            return data;
        }
    
        public void setData(Object data) {
            this.data = data;
        }
    
        /**
         * 将json结果集转化为TaotaoResult对象
         * 
         * @param jsonData json数据
         * @param clazz TaotaoResult中的object类型
         * @return
         */
        public static TaotaoResult formatToPojo(String jsonData, Class<?> clazz) {
            try {
                if (clazz == null) {
                    return MAPPER.readValue(jsonData, TaotaoResult.class);
                }
                JsonNode jsonNode = MAPPER.readTree(jsonData);
                JsonNode data = jsonNode.get("data");
                Object obj = null;
                if (clazz != null) {
                    if (data.isObject()) {
                        obj = MAPPER.readValue(data.traverse(), clazz);
                    } else if (data.isTextual()) {
                        obj = MAPPER.readValue(data.asText(), clazz);
                    }
                }
                return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);
            } catch (Exception e) {
                return null;
            }
        }
    
        /**
         * 没有object对象的转化
         * 
         * @param json
         * @return
         */
        public static TaotaoResult format(String json) {
            try {
                return MAPPER.readValue(json, TaotaoResult.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * Object是集合转化
         * 
         * @param jsonData json数据
         * @param clazz 集合中的类型
         * @return
         */
        public static TaotaoResult formatToList(String jsonData, Class<?> clazz) {
            try {
                JsonNode jsonNode = MAPPER.readTree(jsonData);
                JsonNode data = jsonNode.get("data");
                Object obj = null;
                if (data.isArray() && data.size() > 0) {
                    obj = MAPPER.readValue(data.traverse(),
                            MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
                }
                return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);
            } catch (Exception e) {
                return null;
            }
        }
    
    }
    View Code

    5.1 数据库

    用到tb_item和tb_item_desc两张表:

    5.2 DAO层

    利用反向工程生成的mapper

    5.3 Service层

    taotao-manager-interface下 com.taotao.service包下的 ItemService 类:

    public interface ItemService {/**
         * 添加商品基本数据和描述数据
         * @param item
         * @param desc
         * @return
         */
        public TaotaoResult saveItem(TbItem item,String desc);
    }

    taotao-manager-service下 com.taotao.service.impl的 ItemServiceImpl 实现 saveItem() 方法:

    @Service
    public class ItemServiceImpl implements ItemService {
        
        //注入mapper
        @Autowired
        private TbItemMapper itemMapper;
        @Autowired
        private TbItemDescMapper itemDescMapper;
    
        @Override
        public TaotaoResult saveItem(TbItem item, String desc) {
            //生成商品的id (利用工具类IDUtils下的genItemId()方法生成)
            long itemId = IDUtils.genItemId();
            
            //1.补全item的其他属性
            item.setId(itemId);
            item.setStatus((byte) 1);//1-正常,2-下架,3-删除
            item.setCreated(new Date());
            item.setUpdated(new Date());
            //2.向商品表(item表)插入数据
            itemMapper.insert(item);
            //3.创建一个商品描述表对应的pojo对象
            TbItemDesc itemDesc = new TbItemDesc();
            //4.补全商品描述中的属性
            itemDesc.setItemId(itemId);
            itemDesc.setItemDesc(desc);
            itemDesc.setCreated(new Date());
            itemDesc.setUpdated(new Date());
            //5.插入商品描述数据
            itemDescMapper.insert(itemDesc);
            //6.返回TaotaoResult
            return TaotaoResult.ok();
        }
    
    }

    5.4 Controller层

    @Controller
    public class ItemController {
        
        //1.引入服务(springmvc.xml中引入)
        //2.注入服务
        @Autowired
        private ItemService itemService;
        /**
         * 商品添加功能
         */
        @RequestMapping(value="/item/save",method=RequestMethod.POST)
        @ResponseBody
        public TaotaoResult saveItem(TbItem item, String desc) {
            //1.引入服务(springmvc.xml中引入)
            //2.注入服务(@Autowired ItemService)
            //3.调用
            return itemService.saveItem(item, desc);
        }
    }

  • 相关阅读:
    哪种可以让程序员赚到更多钱?
    layer 弹框 很好用 页面交互不好弄!!!父子弹框的交互!
    博客导航
    扯淡扯着扯着就远了----关键字;宁静致远
    高驰涛——裸奔到北京的程序猿
    TP5分页类使用——超级简单好用
    七牛云同步资源工具使用说明
    短链接实现原理和简单调用
    抓包工具Charles下载地址及Charles配置https
    敲代码的少年
  • 原文地址:https://www.cnblogs.com/toria/p/taotao03.html
Copyright © 2020-2023  润新知