精华内容
下载资源
问答
  • Java实现打印功能

    千次阅读 2018-09-12 15:09:38
    开始是想直接使用Java API的打印方法,具体实现时发现在启用后可以调出打印对话框,但打印机没有反应,查看了网上的很多方法,试了下还是不行,就放弃了。看下Java实现的代码: import java.io.FileInputStream;...

    前段时间项目中刚好有遇到这个需求,具体是实现将上传到服务端的附件进行不下载在线打印,打印时要进行预览。

    一开始是想直接使用Java API的打印方法,具体实现时发现在启用后可以调出打印对话框,但打印机没有反应,查看了网上的很多方法,试了下还是不行,就放弃了。看下Java实现的代码:

    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
     
    import javax.print.Doc;
    import javax.print.DocFlavor;
    import javax.print.DocPrintJob;
    import javax.print.PrintException;
    import javax.print.PrintService;
    import javax.print.PrintServiceLookup;
    import javax.print.SimpleDoc;
    import javax.print.attribute.DocAttributeSet;
    import javax.print.attribute.HashDocAttributeSet;
    import javax.print.attribute.HashPrintRequestAttributeSet;
    import javax.print.attribute.PrintRequestAttributeSet;
    import javax.print.attribute.standard.MediaSizeName;
    import javax.swing.JOptionPane;
     
    public class PrintUtils {
        public static void main(String[] args) {
            FileInputStream textStream = null;
            try {
                textStream = new FileInputStream("C:\\CityLove.pdf");
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } 
             
            //String printStr = "打印测试内容";// 获取需要打印的目标文本
            if (textStream != null) // 当打印内容不为空时
            {
                // 指定打印输出格式
                DocFlavor flavor = DocFlavor.INPUT_STREAM.PDF;//SERVICE_FORMATTED.PRINTABLE
                // 定位默认的打印服务
                PrintService printService = PrintServiceLookup.lookupDefaultPrintService();
                // 创建打印作业
                DocPrintJob job = printService.createPrintJob();
                // 设置打印属性
                PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
                // 设置纸张大小,也可以新建MediaSize类来自定义大小
                pras.add(MediaSizeName.ISO_A4);
                DocAttributeSet das = new HashDocAttributeSet();
                // 指定打印内容
                Doc doc = new SimpleDoc(textStream, flavor, das);
                // 不显示打印对话框,直接进行打印工作
                try {
                    job.print(doc, pras); // 进行每一页的具体打印操作
                } catch (PrintException pe) {
                    pe.printStackTrace();
                }
            } else {
                // 如果打印内容为空时,提示用户打印将取消
                JOptionPane.showConfirmDialog(null,
                        "Sorry, Printer Job is Empty, Print Cancelled!",
                        "Empty", JOptionPane.DEFAULT_OPTION,
                        JOptionPane.WARNING_MESSAGE);
            }
        }
     
     
    }

    之后就采用的POI方法装换文件,将word,Excel转成HTML页面,然后调用浏览器的打印功能。具体如下:

    需要添加的maven依赖,对应版本,否则会报错

    <dependency>
    	<groupId>org.apache.poi</groupId>
    	<artifactId>poi-scratchpad</artifactId>
    	<version>3.15</version>
    </dependency>
    <dependency>
    	<groupId>org.apache.poi</groupId>
    	<artifactId>poi</artifactId>
    	<version>3.15</version>
    </dependency>
    <dependency> 
    	<groupId>org.apache.poi</groupId> 
    	<artifactId>poi-ooxml</artifactId>
    	<version>3.15</version>
    </dependency>
    <dependency>
    	<groupId>org.apache.poi</groupId>
    	<artifactId>ooxml-schemas</artifactId>
    	<version>1.3</version>
    </dependency>
    <dependency> 
        <groupId>fr.opensagres.xdocreport</groupId> 
    	<artifactId>xdocreport</artifactId> 
    	<version>1.0.6</version> 
    </dependency>
    <dependency>
    	<groupId>org.apache.poi</groupId>
    	<artifactId>poi-ooxml-schemas</artifactId>
    	<version>3.15</version><!--$NO-MVN-MAN-VER$-->
    </dependency>

    Java转换方法:

    /**
       * doc转HTML
       */
      public String wordDocToHtml(String filePath) throws Exception {
        InputStream input = new FileInputStream(filePath);
        HWPFDocument wordDocument = new HWPFDocument(input);
        WordToHtmlConverter wConverter =
            new WordToHtmlConverter(DocumentBuilderFactory.newInstance().newDocumentBuilder()
                .newDocument());
    
        wConverter.setPicturesManager(new PicturesManager() {
          @Override
          public String savePicture(byte[] content, PictureType pictureType, String suggestedName,
              float widthInches, float heightInches) {
            return suggestedName;
          }
        });
    
        wConverter.processDocument(wordDocument);
        List list = wordDocument.getPicturesTable().getAllPictures();
        if (list != null) {
          for (int i = 0; i < list.size(); i++) {
            Picture picture = (Picture) list.get(i);
            picture.writeImageContent(new FileOutputStream(filePath + picture.suggestFullFileName()));
          }
        }
    
        Document document = wConverter.getDocument();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        DOMSource domSource = new DOMSource(document);
        StreamResult streamResult = new StreamResult(outputStream);
        TransformerFactory tFactory = TransformerFactory.newInstance();
        Transformer serializer = tFactory.newTransformer();
        serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
        serializer.setOutputProperty(OutputKeys.INDENT, "yes");
        serializer.setOutputProperty(OutputKeys.METHOD, "html");
        serializer.transform(domSource, streamResult);
        outputStream.close();
    
        String content = new String(outputStream.toByteArray());
        String newFilePath = UuidUtil.getTimeBasedUuid() + ".html";
        File file = new File(filePath + newFilePath);
        FileUtils.writeStringToFile(file, content, "utf-8");
    
        return file.getName();
      }
    
    /**
       * docx转HTML
       * 
       * @throws Exception
       */
    
      public String wordDocxToHtml(String filePath, HttpServletRequest request) throws Exception {
        String sysFileString = getSysFilePath(request);
        InputStream input = new FileInputStream(filePath);
        XWPFDocument document = new XWPFDocument(input);
        XHTMLOptions options = XHTMLOptions.create(); // 存放图片的文件夹
    
        options.setExtractor(new FileImageExtractor(new File(sysFileString))); // html中图片的路径
        options.URIResolver(new BasicURIResolver(sysFileString));
        options.setIgnoreStylesIfUnused(false);
        options.setFragment(true);
    
        String newFilePath = UuidUtil.getTimeBasedUuid() + ".html";
        File file = new File(filePath + newFilePath);
    
        OutputStreamWriter outputStreamWriter =
            new OutputStreamWriter(new FileOutputStream(file), "utf-8");
        BufferedWriter bufferedOutputStream = new BufferedWriter(outputStreamWriter);
    
        XHTMLConverter xhtmlConverter = (XHTMLConverter) XHTMLConverter.getInstance();
        xhtmlConverter.convert(document, bufferedOutputStream, options);
    
        if (outputStreamWriter != null) {
          outputStreamWriter.close();
        }
    
        return file.getName();
      }
    
    /**
       * Excel转HTML
       * 
       * @throws Exception
       */
      public String excelToHtml(String filePath, String suffix) throws Exception {
        InputStream input = new FileInputStream(filePath);
        HSSFWorkbook excelBook = null;
        if (suffix.equals("xlsx")) {
          // 将07版转化为03版
          Xssf2HssfUtil xlsx2xls = new Xssf2HssfUtil();
          XSSFWorkbook xSSFWorkbook = new XSSFWorkbook(input);
          excelBook = new HSSFWorkbook();
          xlsx2xls.transformXSSF(xSSFWorkbook, excelBook);
        } else {
          excelBook = new HSSFWorkbook(input);
        }
    
        ExcelToHtmlConverter eHtmlConverter =
            new ExcelToHtmlConverter(DocumentBuilderFactory.newInstance().newDocumentBuilder()
                .newDocument());
        int index = excelBook.getActiveSheetIndex();
        String sheetName = "";
        for (int i = 0; i < index + 1; i++) {
          // 设置字体
          HSSFFont font = excelBook.getFontAt((short) i);
          font.setCharSet(HSSFFont.DEFAULT_CHARSET);
          font.setFontHeightInPoints((short) 8);// 更改默认字体大小
          font.setFontName("黑体");// 更改字体格式
          font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);// 非粗体显示
          // 去掉Excel头
          eHtmlConverter.setOutputColumnHeaders(false);
          // 去掉Excel行号
          eHtmlConverter.setOutputRowNumbers(false);
          // 去掉表名
    
          sheetName = sheetName + " ";
          excelBook.setSheetName(i, sheetName + " ");
        }
    
        eHtmlConverter.processWorkbook(excelBook);
        List pics = excelBook.getAllPictures();
        if (pics != null) {
          for (int i = 0; i < pics.size(); i++) {
            Picture pic = (Picture) pics.get(i);
            pic.writeImageContent(new FileOutputStream(filePath + pic.suggestFullFileName()));
          }
        }
    
        Document htmlDocument = eHtmlConverter.getDocument();
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        DOMSource domSource = new DOMSource(htmlDocument);
        StreamResult streamResult = new StreamResult(outStream);
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer serializer = tf.newTransformer();
        serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
        serializer.setOutputProperty(OutputKeys.INDENT, "yes");
        serializer.setOutputProperty(OutputKeys.METHOD, "html");
        serializer.transform(domSource, streamResult);
        outStream.close();
    
        String content = new String(outStream.toByteArray());
        String newFilePath = UuidUtil.getTimeBasedUuid() + ".html";
        File file = new File(filePath + newFilePath);
        FileUtils.writeStringToFile(file, content, "utf-8");
    
        return file.getName();
      }

    最终虽然大致实现了功能,但是还有很多问题,在文件转换时,有很多样式没法保存,比如说有的下划线丢失了,文档的对齐格式跑偏。这几个问题有尝试去修改,在网上也搜了很多,没有找到解决方法。个人觉得还是把文件转成PDF格式,再去进行操作可能会更好一点。

    希望分享对大家有所帮助,欢迎留言改进。

    展开全文
  • 基于Java的商品管理功能实现

    千次阅读 2019-07-18 20:12:48
    完成一个电商系统的商品模块功能,商品类包含以下属性:商品ID,商品名,类别名,单价,库存量,产地,计量单 位等信息,要求实现商品管理功能具体如下: 商品添加 商品列表 查询指定id的商品 根据商品id删除...

    基于Java的商品管理功能的实现

    1.具体内容:

    完成一个电商系统的商品模块功能,商品类包含以下属性:商品ID,商品名,类别名,单价,库存量,产地,计量单                           位等信息,要求实现商品管理功能,具体如下:

    商品添加

    商品列表

    查询指定id的商品

    根据商品id删除商品

    根据id修改指定商品的价格

    根据id修改指定商品的库存

    根据商品类别查询所有商品

    查询指定价格区间的商品信息

    2.实现步骤

    为了防止一个类中代码过长,我创建三个类来实现功能:

    (1)创建商品类:根据商品的属性建立变量(私有化),通过创建set方法和get方法让外界获取,为了方便输入商品信息,创建带参数的构造器,为了方便输出语句创建toString()方法。

    (2)创建商品管理类:根据需要实现的管理功能创建方法(这里简化不用Scanner,所以用void,方法中没有返回值)。

    (3)创建测试类:通过创建测试类来测试方法的具体功能。

    3.具体代码实现:

    Comm类:

    package com.softeem.homework;
    
    /**
     * 
     * @author ASUS
     *
     */
    public class Comm {
    
    	private int cid;
    	private String cname;
    	private String lname;
    	private double price;
    	private int num;
    	private String address;
    	private String unit;
    	public Comm(int cid, String cname, String lname, double price, int num, String address, String unit) {
    		super();
    		this.cid = cid;
    		this.cname = cname;
    		this.lname = lname;
    		this.price = price;
    		this.num = num;
    		this.address = address;
    		this.unit = unit;
    	}
    	public int getCid() {
    		return cid;
    	}
    	public void setCid(int cid) {
    		this.cid = cid;
    	}
    	public String getCname() {
    		return cname;
    	}
    	public void setCname(String cname) {
    		this.cname = cname;
    	}
    	public String getLname() {
    		return lname;
    	}
    	public void setLname(String lname) {
    		this.lname = lname;
    	}
    	public double getPrice() {
    		return price;
    	}
    	public void setPrice(double price) {
    		this.price = price;
    	}
    	public int getNum() {
    		return num;
    	}
    	public void setNum(int num) {
    		this.num = num;
    	}
    	public String getAddress() {
    		return address;
    	}
    	public void setAddress(String address) {
    		this.address = address;
    	}
    	public String getUnit() {
    		return unit;
    	}
    	public void setUnit(String unit) {
    		this.unit = unit;
    	}
    	@Override
    	public String toString() {
    		return  cid + "\t" + cname + "\t" + lname + "\t" + price + "\t" + num
    				+ "\t" + address + "\t" + unit ;
    	}
    	
    }

    CommManage类

    package com.softeem.homework;
    
    import java.util.ArrayList;
    
    
    /**
     * 商品管理
     * @author ASUS
     *
     */
    public class CommManage {
    
    	static ArrayList<Comm> list = new ArrayList<>();
    	
    	/**添加商品*/
    	public void add(Comm comm){
    		list.add(comm);
    	}
    	
    	/**商品列表*/
    	public void findAll(){
    		for(Comm c:list){
    			System.out.println(c);
    		}
    	}
    	
    	/**根据id查询商品*/
    	public Comm findByCid(int cid){
    		Comm comm = null;
    		for(Comm c:list){
    			//判断是否找到匹配id的商品
    			if(c.getCid() == cid){
    				comm = c;
    				msg(comm);
    				break;
    			}
    		}
    		return comm;
    	}
    	
    	/**根据id删除商品*/
    	public boolean delete(int cid){
    		Comm comm = findByCid(cid);
    		if(comm != null){
    			return list.remove(comm);
    		}
    		return false;
    	}
    	
    	/**根据id修改商品价格*/
    	public boolean updatePrice(int cid,double price){
    		Comm comm = findByCid(cid);
    		if(comm != null){
    			comm.setPrice(price);
    
    			return true;
    		}
    		return false;
    	}
    	/**根据id修改商品库存*/
    	public boolean updateUnit(int cid,int num){
    		Comm comm = findByCid(cid);
    		if(comm != null){
    			comm.setNum(num);
    			
    			return true;
    		}
    		return false;
    	}
    	/**根据商品类别查询所有商品*/
    	public ArrayList<Comm> findByLname(String lname){
    		ArrayList<Comm> comm = new ArrayList<>();
    		for(Comm c:list){
    			//查询集合中是否存在员工的部门名称跟参数部门名一致
    			if(lname.equals(c.getLname())){
    				comm.add(c);
    				msg(c);
    			}
    		}
    		return comm;
    	}
    	/**根据商品类别查询所有商品*/
    	public ArrayList<Comm> findByPrice(double price1,double price2){
    		ArrayList<Comm> comm = new ArrayList<>();
    		for(Comm c:list){
    			// 查询指定价格区间的商品
    			if(price1 <= c.getPrice()&& c.getPrice() <= price2){
    				comm.add(c);
    				msg(c);
    			}
    		}
    		return comm;
    	}
    	/**输出语句*/
    	public void msg(Object obj){
    		System.out.println(obj);
    	}
    	
    }

    Test类

    package com.softeem.homework;
    
    public class Test {
    
    	public static void main(String[] args) {
    		Comm c1 = new Comm(101,"抱枕","家用",120,500,"杭州","件");
    		Comm c2 = new Comm(102,"棉被","家用",320,800,"杭州","件");
    		Comm c3 = new Comm(103,"床单","家用",80,600,"杭州","件");
    		Comm c4 = new Comm(104,"冰箱","电器",1200,500,"深圳","件");
    		Comm c5 = new Comm(105,"汽车","工具",32000,1500,"香港","辆");
    		Comm c6 = new Comm(106,"手机","电器",1120,3500,"香港","部");
    		
    		CommManage cm = new  CommManage(); 
    		cm.add(c1);
    		cm.add(c2);
    		cm.add(c3);
    		cm.add(c4);
    		cm.add(c5);
    		cm.add(c6);
    //		cm.findAll();
    //		cm.findByCid(103);
    //		cm.delete(103);
    //		cm.findAll();
    //		cm.updatePrice(101, 200);
    //		cm.updateUnit(104, 1000);
    //		cm.findAll();
    //		cm.findByLname("家用");
    		cm.findByPrice(100, 500);
    		
    	}
    }

    添加商品

    查询指定id的商品,根据商品id删除商品

    根据id修改指定商品的价格,根据id修改指定商品的库存

    根据商品类别查询所有商品,查询指定价格区间的商品信息

    展开全文
  • java实现收藏功能

    千次阅读 2020-08-18 16:17:00
    java实现收藏功能 需求分析 分析: 1.要求用户必须登录,否则提示 2.第次点击,表示收藏成功,收藏数+1,显示蓝色星星 3.第二次点击,表示取消收藏操作,收藏数-1,显示白色星星 ------------------------------------...

    java实现收藏功能

    在这里插入图片描述

    需求分析
    分析:
        1.要求用户必须登录,否则提示
    	2.第一次点击,表示收藏成功,收藏数+1,显示蓝色星星
    	3.第二次点击,表示取消收藏操作,收藏数-1,显示白色星星
    -----------------------------------------------------------------------
    	核心问题:当前请求时收藏操作,还是取消收藏操作
    	[这类型的操作,称之为有状态的操作]
    解决方案:第一次请求过来时,留下一个记号,第二次请求时候,根据记号有无决定收藏还是取消收藏
    	引出新问题:记号怎么设计
    ----------------------------------------------------------
        记号应该存在缓存中,而不是mongodb/mysql
    原因:现在所有操作都是缓存里面操作,也即:使用redis来缓存集合,此时需要思考,key值与value值设计
    

    在这里插入图片描述

    步骤分析
    //判断是否存在以用户id为key的key键,返回list	
    	1.创建一个收藏接口,传攻略sid,获取用户uid
    	2.请求进入之后需要判断是收藏操作还是取消收藏操作
    	3.通过uid拼接出用户收藏的攻略id集合(记号)的key
    	4.判断key是否存在,如果存在,直接获取sidList,如果不存在,返回空集合list
    //判断是取消收藏还是收藏操作,返回boolean类型
    	5.判断当前传入的sid是否在sidList(攻略id集合)1>如果不在,当前请求为收藏请求,获取vo对象,收藏数+1,将sid添加到sidList(攻略id集合)
            2>如果在,当前请求为取消收藏请求,获取vo对象,收藏数-1,将sid从sidList(攻略id集合)移除
    	6.更新sidList(攻略id集合),更新vo对象
    	
    //从redis中取出来的集合字符串转换为集合
    	JSON.parseArray(集合字符串,String.class)
    
    具体实现
       //获取收藏数id集合
        @Override
        public List<String> getStrategyFavorStatisVO(String userId, String sid) {
            //拼接key
            String key = RedisKeys.USER_STRATEGY_FAVOR.join(userId);
            //判断redis中有没有该key
            List<String> list = new ArrayList<>();
            if (template.hasKey(key)) {
                //如果存在,就直接获得key对应的收藏数集合
                String sidListStr = template.opsForValue().get(key);
                //将字符串解析为集合
                list = JSON.parseArray(sidListStr, String.class);
            }
            //如果不存在,创建list,缓存到redis中,并返回空集合
            return list;
        }
    
        //判断集合中是否存在攻略id
        @Override
        public boolean isExistsSid(String uid, String sid) {
            List<String> list = this.getStrategyFavorStatisVO(uid, sid);
            StrategyStatisVO statisVO = this.getStrategyStatisVO(sid);
            //判断是否在存在传过来的攻略id
            if (!list.contains(sid)) {
                //不存在,收藏操作,收藏数+1,添加到list集合中
                statisVO.setFavornum(statisVO.getFavornum() + 1);
                list.add(sid);
            } else {
                //存在,取消收藏操作,收藏数-1,并从list集合中移除
                statisVO.setFavornum(statisVO.getFavornum() - 1);
                list.remove(sid);
            }
            //更新vo对象,更新list
            this.setStrategyStatisVO(statisVO);
            template.opsForValue().set(RedisKeys.USER_STRATEGY_FAVOR.join(uid), JSON.toJSONString(list));
            return list.contains(sid);
        }
    ------------------------------------------------------------------------------------
    	//获取vo对象
     	@Override
        public StrategyStatisVO getStrategyStatisVO(String sid) {
            //使用枚举类拼接key
            String key = RedisKeys.STRATEGY_STATIS_VO.join(sid);
            StrategyStatisVO statisVO = new StrategyStatisVO();
            //判断vo对象是否存在,即判断key是否存在
            if (!template.hasKey(key)) {
                //不存在,初始化数据,将数据查出来,然后赋值给vo对象,最后存起来
                Strategy strategy = strategyService.get(sid);
                BeanUtils.copyProperties(strategy, statisVO);
                statisVO.setStrategyId(sid);
                template.opsForValue().set(key, JSON.toJSONString(statisVO));
            } else {
                //存在,获取vo对象
                String VO = template.opsForValue().get(key);
                statisVO = JSON.parseObject(VO, StrategyStatisVO.class);
            }
            return statisVO;
        }
    	//设置vo对象,将vo对象存储到redis数据库中
    	 @Override
        public void setStrategyStatisVO(StrategyStatisVO statisVO) {
            String key = RedisKeys.STRATEGY_STATIS_VO.join(statisVO.getStrategyId());
            template.opsForValue().set(key, JSON.toJSONString(statisVO));
        }
    
    小结
       1.关于收藏功能的实现其实与点赞功能类似,都是点击一下,数据+1,再点击一下,数据-1
       2.关于这类问题,我们称之为有状态的操作,就是第一次操作之后,我们需要留下一个记号(key键,value-list集合)
       3.例如上面的操作,我们用key键作为标记,key键通过当前用户id拼接,站在用户角度
       4.先判断key键是否存在,存在,就通过key取出list集合,不存在,返回空集合给前端,这个是用来显示收藏颜色的
       5.当我们点击操作时,只需要判断传进来的攻略id是否存在集合中即可
       6.如果不在,当前请求为收藏请求,获取vo对象,收藏数+1,将sid添加到sidList(攻略id集合)
         如果在,当前请求为取消收藏请求,获取vo对象,收藏数-1,将sid从sidList(攻略id集合)移除
       7.最后更新sidList(攻略id集合),更新vo对象即可
    
    展开全文
  • Java+MySQL实现评论功能设计开发

    万次阅读 多人点赞 2018-08-13 09:39:52
    Java+MySQL实现评论功能设计开发 、背景 项目初始版本上线,有时间写点东西记录一下项目中的心得体会,通过这项目学习了很多,要写下来的有很多,先从评论功能开始吧。由于项目需要增加评论功能,之前并无此...

                                                    Java+MySQL实现评论功能设计开发

    一、背景

          项目初始版本上线,有时间写点东西记录一下项目中的心得体会,通过这个项目学习了很多,要写下来的有很多,先从评论功能开始吧。由于项目需要增加评论功能,之前并无此方面的经验,因此项目开始的一段时间都在寻思着如何进行评论功能的设计。上网搜索一波发现有很多优秀的第三方评论插件可以使用,本来准备直接采用的,但是心里始终有点疙瘩,可能是评论数据放在别人那里不放心的原因,或可能是想一探这些评论系统的究竟,因此最终决定自行设计开发这么一套评论功能。效果截图如下所示,采用的是MySQL数据库,编程语言用的Java。(更好的阅读体验,请移步我的个人博客)

    二、评论系统的概述:

           评论功能是用户表达对某一主题的想法的很好的一种方式,优秀的评论系统能很好地提高社区的活跃度。各大主流网站也都提供了相应的评论支持。比如:贴吧,新闻类门户网站(APP),UC浏览器等等。

          各大网站侧重点不同,对评论功能的要求就不一样,设计出来的评论系统自然就不一样。可能会有:①只可以进行评论,不可以回复,②既可以进行评论,也可以进行回复,然后在这个基础上可能会增加一些额外的功能,比如评论的折叠,审核,优选等。另外,一个良好的UI显示也是非常重要的,能给用户一个直观的视觉上的体验也是评论功能不可或缺的一个要素,毕竟用户都是具有很强的审美能力的,用户的使用体验决定了项目的需求。

          对于本项目,设计的是,既可以评论,也可以进行回复,评论和回复分开存储。在显示上,评论和回复显示的位置不同,回复相较于评论向右靠一些,这样,看起来比较舒适,当然也可以设置成其他的样式。评论会显示评论者头像,回复不会。

          评论的管理:后台系统应该具备基本的评论管理功能,比如:删除,折叠,优选,排序。这些功能的实现依赖于数据库表的设计,所以,在开始设计的时候,要想清楚自己的项目需要哪些功能。

    三、数据库表的设计:

         本评论功能采用评论和回复分离的方式进行存储,一共设计了两张表,一张用户评论表(comment),一张针对评论的回复表(comment_reply)。评论表主要保存对文章或者回答的评论,回复表保存对每一条评论的回复。

          评论表(comment)如下图:主要包括了:评论ID(作为回复表的主键),回答(文章)ID,评论者ID,评论内容,点赞数,评论时间,审核状态

         评论回复表(comment_reply)如下图:主要包括了:评论ID,用户ID,被回复人ID,回复内容,点赞数,回复时间。

          两张表通过comment_id联系起来(并没有设置主外键,主要是不想维护起来太麻烦),获取某一答案的评论及回复步骤:根据answer_id找到所有的评论,然后,遍历所有的评论,根据comment_id查询到所有的回复(评论者的基本信息,例如头像,名称等需要额外查询)。需要注意的是,在评论和回复数据较多的情况下做好分页处理。

    四、程序的实现: 

          采用Java语言进行编程的实现,使用的SSM框架。主要的功能代码如下所示(因为项目有通知功能,看的时候可以略过这部分,跟单纯的评论功能没有太大关系,但是一般要有通知,后面有时间会写站内通知的设计与开发博客):

       4.1 添加评论代码如下:(获取到评论相关的参数,然后进行向数据库表插入)

    public int addComment(Comment comment) {
    	try {
    		Answer commentAnswer = answerMapper.selectByPrimaryKey(comment.getAnswerId());
    		Long commentId = IDUtils.genItemId();//评论ID
    		Date createtime = new Date();
    		//1,填补comment对象的其他参数,进行插入
    		comment.setCommentId(commentId);
    		comment.setState(1);//状态: 0 待审核,1通过,2不通过
    		comment.setPraseCount(0);//一开始插入的点赞数设置为0
    		comment.setCreatetime(createtime);
    		comment.setUpdatetime(createtime);
    		commentMapper.insert(comment);//插入comment记录
    		//2,跟新Answer的相关一条数据,提示评论数+1
    		commentAnswer.setCommentNum((commentAnswer.getCommentNum()==null?0:commentAnswer.getCommentNum()) + 1);
    		answerMapper.updateByPrimaryKeySelective(commentAnswer);
    		//3,向提醒表插一条数据。这条评论是发给谁的,通知表里面的userId就是谁
    		if (comment.getUserId() != commentAnswer.getUserId()) { //自己评论自己不会有通知
    			Remind remind = new Remind();
    			remind.setRemindId(commentId);
    			remind.setUserId(commentAnswer.getUserId());
    			remind.setFromUserId(comment.getUserId());
    			//commentType:1评论回答,2评论别人的评论,3关注,4支持,5反对,6添加回答
    			remind.setRemindType(1);
    			//已读:0否,1是
    			remind.setReadStatus(0);//否
    			remind.setCreatetime(createtime);
    			//插入通知内容,以json的形式存储
    			RemindContent remindComment = new RemindContent();
    			remindComment.setContentId(commentAnswer.getAnswerId());
    			remind.setContent(JsonUtils.objectToJson(remindComment));//通知内容。回答问题的Id
    			remindMapper.insert(remind);
    		}
    		//返回1代表成功
    		return 1;
    	} catch (Exception e) {
    		e.printStackTrace();
    		return 2;
    	}
    }

     4.2 添加回复代码:(前台会传来评论的ID,然后,封装成回复对象进行插入,一个评论ID会对应很多回复)

    public int addCommentReply(CommentReply commentReply) {
        Long commentId = IDUtils.genItemId();//评论ID
        Date createtime = new Date();
    	commentReply.setPraseCount(0);
    	commentReply.setCreatetime(createtime);
    	int retVal = commentReplyMapper.insert(commentReply);
    	  
        //3,向提醒表插一条数据。这条评论是发给谁的,通知表里面的userId就是谁
    	if (commentReply.getReplyuserId() != commentReply.getUserId()) {
    	    Remind remind = new Remind();
    		remind.setRemindId(commentId);
    	    remind.setUserId(commentReply.getReplyuserId());
    		remind.setFromUserId(commentReply.getUserId());
    		//commentType:1评论回答,2评论别人的评论,3关注,4支持,5反对,6添加回答
    		remind.setRemindType(2);
    		//已读:0是,1否
    		remind.setReadStatus(1);
    		remind.setCreatetime(createtime);
    		remind.setContent(commentReply.getCommentId()+"");
    		remindMapper.insert(remind);
    	}
    	return retVal;
    }

     4.3获取某一回答的评论和回复(评论分页返回,但是回复没有分页,后面会优化,使用的是pagehelper插件):

    public PageBean<CommentStatus> listAnswerComments(Long answerId,Integer pageNum,Integer pageSize) {
    try {
    	CommentExample commentExample = new CommentExample();
    	commentExample.setOrderByClause("createtime DESC");
    	Criteria commentCriteria = commentExample.createCriteria();
    	commentCriteria.andAnswerIdEqualTo(answerId);
    	PageHelper.startPage(pageNum, pageSize);
    	List<Comment> commentList = commentMapper.selectByExampleWithBLOBs(commentExample);//获取具有分页结果的评论数据
    	List<CommentStatus> commentStatusList = new ArrayList<>();
    	for (Comment comment : commentList) {
    		CommentStatus commentStatus = new CommentStatus(); //评论返回的具体对象
    			
    		CommentReplyExample example = new CommentReplyExample();
    		com.pn.mini.model.CommentReplyExample.Criteria criteria = example.createCriteria();
    		criteria.andCommentIdEqualTo(comment.getCommentId());
    		List<CommentReply> commentReplyList = commentReplyMapper.selectByExample(example);
    		List<CommentReplyStatus> commentReplyStatusList = new ArrayList<>();
    		for (CommentReply commentReply2 : commentReplyList) {
    			UserBaseInfo commentUser = userBaseInfoMapper.selectByPrimaryKey(commentReply2.getUserId());
    			UserBaseInfo commentReplyUser = userBaseInfoMapper.selectByPrimaryKey(commentReply2.getReplyuserId());
    			CommentReplyStatus commentReplyStatus = new CommentReplyStatus();
    			commentReplyStatus.setCommentId(commentReply2.getCommentId());
    			commentReplyStatus.setContent(commentReply2.getContent());
    			commentReplyStatus.setCreatetime(commentReply2.getCreatetime());
    			commentReplyStatus.setPraseCount(commentReply2.getPraseCount());
    			commentReplyStatus.setReplyuserId(commentReply2.getReplyuserId());
    			commentReplyStatus.setReplyuserName(commentReplyUser.getUserName());
    			commentReplyStatus.setUserId(commentUser.getUserId());
    			commentReplyStatus.setUserName(commentUser.getUserName());
    			commentReplyStatusList.add(commentReplyStatus);
    		}
    		UserBaseInfo commentUserBaseInfo = userBaseInfoMapper.selectByPrimaryKey(comment.getUserId());
    		CommentIntegrate commentIntegrate = new CommentIntegrate();
    		commentIntegrate.setAnswerId(comment.getAnswerId());
    		commentIntegrate.setAvatar(commentUserBaseInfo.getAvatar());
    		commentIntegrate.setCommentId(comment.getCommentId());
    		commentIntegrate.setContent(comment.getContent());
    		commentIntegrate.setCreatetime(comment.getCreatetime());
    		commentIntegrate.setPraseCount(comment.getPraseCount());
    		commentIntegrate.setState(comment.getState());
    		commentIntegrate.setUpdatetime(comment.getUpdatetime());
    		commentIntegrate.setUserId(comment.getUserId());
    		commentIntegrate.setUserName(commentUserBaseInfo.getUserName());
    		//拼接一条评论的返回对象
    		commentStatus.setCommentIntegrate(commentIntegrate);
    		commentStatus.setCommentReplyStatusList(commentReplyStatusList);
    		commentStatusList.add(commentStatus);
    	}
    	PageBean<CommentStatus> recCommentItemBean = null;//接口返回的对象
    	PageInfo<Comment> pageInfo = new PageInfo<>(commentList);
    	recCommentItemBean = new PageBean<>(commentStatusList);
    	recCommentItemBean.setDataList(commentStatusList);
    	recCommentItemBean.setPageNum(pageInfo.getPageNum());
    	recCommentItemBean.setPages(pageInfo.getPages());
    	recCommentItemBean.setPageSize(pageInfo.getPageSize());
    	recCommentItemBean.setSize(pageInfo.getSize());		 
        recCommentItemBean.setTotal(pageInfo.getTotal());
    	return recCommentItemBean;
    			
    	} catch (Exception e) {
    		e.printStackTrace(); //出现异常返回null,controller根据此判断此处调用是否成功
    		return null;
    	}	
    }

     4.4  优化思考:

       ① 回复没有分页返回,回复数据量大的时候需要分页,在在获取回复的时候分页一下即可。

       ② 获取一条信息,需要再去查询用户表,获取用户的信息,这样就会导致获取一条回答的评论和回复需要查询N次数据表,思考的是增加冗余字段(用户名,用户头像),然后减少这方面的查询开销,当用户头像和名称更改的时候,同步更改这里面的数据,但是一般用户的这方面信息更改较少,总的来说,增加这个冗余字段还是能很大程度提高效率的。

      ③优化后的数据库表如下(忽略hot_value这样的字段,不同项目有不同需求):

     

    五:总结与反思(后续优化的方向):

           虽然评论功能开发完毕,在目前也可以正常的使用,待使用程序的用户的增加,流量的扩大后仍需要继续优化,不然在用户的使用体验上可能会很糟糕,尤其是当数据量大的时候,用户访问可能会感觉到有些慢。不足之处其一:在于获取评论的回复,每次读取数据的时候,需要遍历每一条评论,然后去查找这个评论下的所有回复,之后返回这些数据,这样就会造成获取一片文章的评论需要多次查找数据库,效率就会很低,下一步准备从数据库设计和程序实现两个方面去思考如何优化;其二在于:所有文章的评论都在一张表里面,评论的回复也都在一张表里面,这样就会导致表的条目很多,下一步优化的思路集中于分表操作,具体的实现还在思考中。。。。

         评论功能的设计还有很多需要优化的地方,欢迎对这方面有了解的小伙伴一起交流。

    展开全文
  • JAVA实现邮箱注册功能

    万次阅读 2018-11-27 10:49:55
    现在我们来看下是如何具体实现一个邮箱注册的功能。 第一步、先选用个邮箱作为实例 以QQ邮箱为例,开启POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务,具体步骤如下图 第二步、在maven中添加一个jar包,名字...
  • 首先,先上老师给的文档,具体代码在后面   1、安装数据库服务器mysql和数据库客户端navicat。 (1)数据库服务器为绿色版,直接将附件mysql解压即可。 (2)数据库服务启动:双击解压目录里的mysql_start_utf8...
  • Java 简单树的实现具体实例

    千次阅读 2018-09-12 17:33:14
    树与二叉树的实现差不多,二叉树类变量里面有两个自节点,树的类里面有一个树类的链表,下面看具体实现 public class MuxTree { private MyString data; public MuxTree parent; public List&...
  • Java Swing实现JList添加JCheckBox复选框

    千次阅读 2018-06-27 21:42:50
    最近因项目需要具体在JList 框内添加复选框, 网上找了下相关例子,进行下改造,记录一下,这需要实现功能的话就必须重写复选框JCheckBox。 话不多说我们贴上段图 大概书写一番,Jlist单纯添加数据进去之后大概...
  • Java后台实现文件下载功能

    万次阅读 2017-03-13 14:46:26
    在项目中需要做一个功能。就是一个报表。然后根据报表生成一个csv格式的文件。然后进行压缩。并提供下载功能。 该“Excel下载” 功能的业务逻辑是当点击该按钮。则需要把报表页面上显示的数据进行生成一个csv 格式...
  • 手把手教你用Java设计并实现一个城市公交查询系统

    千次阅读 多人点赞 2020-12-19 10:11:33
    为了使得我国公交乘客出行及查询有关信息更方便,本文运用JAVA语言技术,Jsp技术,Mysql数据库开发了B/S结构的城市公交查询系统。 该系统顺应了时代发展且具有以下优点:首先,方便乘客的出行,乘客不用询问站牌工作...
  • Java实现发邮件功能

    千次阅读 2016-08-17 09:20:42
    package com.qincloud.test; import java.util.Date; import java.util.Enumeration; import java.util.Properties; import java.util.Vector; import javax.activation.DataHandler; import javax.activa
  • java实现点赞(顶)功能

    千次阅读 2020-08-18 16:54:12
    java实现点赞(顶)功能 需求分析 分析: 1.必须先登录,否则提示 2.第次点赞(顶),点赞操作,点赞数+1,提示顶成功 2.第二次点赞(顶),没有操作,提示今天顶过了 --------------------------------------------- 核心...
  • java web实现打印功能

    千次阅读 2013-07-16 15:43:27
    直接在网上上进行打印,目前我知道有三种,好吧我承认其实就种。 1直接右键打印,不好的地方就是如果你有iframe在里面的话其他iframe会一起打印出来。 2用js函数window.print进行打印,好处就是基本上能满足基本...
  • 学生管理系统包括:学生信息登录、注册、删除、添加、查询等功能。最关键的也就是查询系统的实现。至于界面的设计前端事情我们不管。 下面是效果图。 界面效果实在一般,不会前端设计,也不想copy,将就看吧。...
  • JAVA 实现钉钉机器人预警推送功能

    千次阅读 2019-07-19 23:36:56
    JAVA 实现钉钉机器人预警推送功能
  • Java小游戏实现》:坦克大战(最后一点附加功能实现)相关博文《Java小游戏实现》:坦克大战http://blog.csdn.net/u010412719/article/details/51712663《Java小游戏实现》:坦克大战(续):...
  • JAVA项目实现授权 ()

    万次阅读 多人点赞 2018-10-09 18:51:30
    JAVA项目实现授权部署 ()    如果项目部署到服务器上,需要当前服务器授权后才能正常访问,也就是说,控制项目的部署位置。当项目部署完成,进行访问时,忽然弹出了下边的小窗口。    看起来挺高大上的,没有...
  • 为了帮助网友解决“java怎么实现一个类中放置监听器,而”相关的问题,中国学网通过互联网对“java怎么实现一个类中放置监听器,而”相关的解决方案进行了整理,用户详细问题包括:RT,我想知道:java怎么实现一个...
  • 本资源是本人前面发过的一个局域网聊天工具的升级版。主要在界面上进行了美化,并添加了语音聊天的功能具体功能有: 1.采用了全新的界面风格(新增) 2.实现了基本文字聊天功能 3.实现了基本文件传送功能 4.实现了...
  • JAVA登录界面的实现

    万次阅读 多人点赞 2018-06-16 09:42:57
    学习JAVA的过程中,登录界面是多数人第一个实现的小程序。今天我们就来做一下登录界面。当然在动手写代码之前我们要先做一些准备工作,我们要先了解JAVA提供的图形界面类有哪些,以及有哪些常用的组件类和辅助类。 ...
  • 仿QQ聊天软件java实现

    万次阅读 多人点赞 2018-01-31 21:28:11
    之前学java通信的时候写过简单的通信程序,但比较简陋,于是重新写了一个仿照QQ的聊天软件,主要在界面上做了优化,增加了一些功能实现功能有注册、登录、好友列表、分组、黑名单、添加好友、群列表、创建群、...
  • Java如何在Cmd实现清屏功能

    千次阅读 2015-10-24 20:21:26
    Java进阶: 使用 Jni 调用 Dll 的实现(使用VS2008 生成Dll) http://www.cnblogs.com/charley_yang/archive/2011/03/15/1985494.html 前言 -----------------------本前言来自网络---------------------...
  • Java实现经典坦克大战及源代码下载

    万次阅读 多人点赞 2017-01-08 11:22:45
    这是一个功能相对全的JAVA版坦克大战,界面绘制是通过JAVA的图形化用户界面完成的,包括了菜单界面和游戏界面。其中菜单界面可以供玩家选择重新开始游戏、暂停、继续、是否播放背景音乐、帮助等操作;游戏界面绘制了...
  • java自定义注解实现日志功能

    千次阅读 2019-07-17 10:16:19
    、spring aop的通知类型 1、前置通知(@Before):在连接点前执行,不会影响连接点的执行,除非抛异常; 2、后置通知(@AfterReturning):在连接点正常执行完成后执行,若连接点抛出异常,则不执行; 3、后置...
  • Java 实现在线给word 文档添加水印

    千次阅读 2019-09-14 01:20:06
    在线编辑文档后需要添加专属水印。防止文档被盗用。 2:方案 用pageoffice提供的添加水印的方法 3:核心代码 (1)后台方法添加文字水印 doc.getWaterMark().setText("PageOffice开发平台"); (2)后台方法...
  • 我们日常使用的软件或者网站,大部分都在使用短信业务,比如 注册 、 验证码功能 。还有一些特定的业务需要发送短信通知用户等。有了需求就会有平台提供服务,国内有很多互联网公司都提供短信业务,比如阿里、腾讯、...
  • Java+MySQL实现学生管理系统

    万次阅读 多人点赞 2019-06-13 15:43:41
    实现一个学生管理系统,方便老师对学生信息进行统计管理 用户登录功能 学生管理功能 完善界面交互 数据持久可靠 设计思路 使用Java作为开发语言,MySQL作为数据库,Java Swing做图形界面; 分层解耦,分为entity...
  • Java实现发送短信验证验证码功能

    万次阅读 2015-04-17 20:13:59
    这几天老大让我弄一个发送短信验证码的功能,使用的是信易通的短信平台接口,然后在Java中使用HttpClient模拟POST请求或者GET请求(看短信平台要求,一般的情况下都是POST请求),调用短信平台提供的接口(遵循短信...
  • Java项目练习10_实现一个简单的学生成绩管理系统

    千次阅读 多人点赞 2018-12-16 14:57:49
    基于命令行模拟实现一个简单的学生成绩信息管理系统,要求实现以下功能: 设计学生信息类,要求信息包括学号、姓名、成绩等属性; 涉及主功能菜单,要求功能涵盖: 输入学生信息 由姓名查询 由学号查询 由...
  • 如题,使用poi组件实现上述功能,如下代码,参考资料地址:http://www.iteye.com/problems/65191: package com.rmsClient.util; import java.io.FileNotFoundException; import java.io.FileOutputStream; import ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 392,808
精华内容 157,123
关键字:

java的一个添加功能的具体实现

java 订阅