Jsp+Servlet+JDBC新聞發佈系統2.0

 

很久之前寫了這樣一篇博客,就很久沒有更新博客了,後面陸陸續續有朋友在下面評論,詢問一些問題。由於之前寫的實在是時代久遠,索性直接重構了一遍,重構過後的系統界面如下:

開發環境:

 

  • windows
  • eclipse
  • mysql

體驗區https://nicecoder.cn/newspublishsystem

管理員界面https://nicecoder.cn/newspublishsystem/login

 

首頁

首頁還沿用之前的樣式,稍作調整。提供按條件查詢新聞,可以根據新聞類型關鍵字類型+關鍵字進行檢索。

 

  • 加載方式採用了無限下拉分頁加載,判斷滾動條到了底部:$(window).scrollTop() == $(document).height() - $(window).height()
$(function(){
	var flag = 0;
	$(window).scroll(function(){  
		if ($(window).scrollTop() == $(document).height() - $(window).height()) {
			var pageCount = $("input[name='pageCount']").val();
			var pageNo = $("input[name='pageNo']").val();
			var keyWord = $("input[name='keyWord']").val();
			var type = $("input[name='type']").val();
			if(pageNo < pageCount){
				$.ajax({
					url:"coreServlet?bizCode=7",
					dataType:"json",
					data:{'keyword':keyWord, 'type':type, 'pageNo':parseInt(pageNo)+1},
					success:function(data){
						var html = "";
						$.each(data.newsList, function(i,val){      
							html += '<div class="new"> ';
							html += '	<div class="content row">';
							html += '		<div class="imgdiv">';
							html += '			<a href="coreServlet?bizCode=4&id='+val.id+'"><img src="'+val.img+'"/></a>';
							html += '		</div>';
							html += '		<div class="text">';
							html += '			<a href="coreServlet?bizCode=4&id='+val.id+'"><h4>"'+val.title+'</h4></a>';
							html += '			<p class="p1">"'+val.pudate+'-"'+val.type+'-"'+val.author+'-閱"'+val.click+'</p>';
							html += '			<p class="p2">"'+val.content+'</p>';
							html += '		</div>';
							html += '	</div>';
							html += '</div>	';
						});
						
						$(".new").last().after(html);
						$("input[name='pageNo']").val(parseInt(pageNo) + 1);
					}
				});
			}else if(pageNo == pageCount && flag == 0){
				flag ++;
				var html = '<p style="text-align:center; color:#FF8C69; font-size:14px; margin-top:10px; margin-bottom:10px;">-沒有更多了-</p>';
				$(".new").last().after(html);
			}
		}
	});  
});

 

  • 時間格式化:採用自定義jstl標籤。

 

  1.    WEB-INF下面創建mytag.tld
    <?xml version="1.0" encoding="UTF-8"?>     
    <taglib xmlns="http://java.sun.com/xml/ns/j2ee"    
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"    
         version="2.0">     
         <tlib-version>1.0</tlib-version>     
         <short-name>myTag</short-name>     
         <function>     
             <description>date change</description><!-- 對這個EL方法的描述   -->     
             <name>formatDate</name><!-- 調用EL方法的名稱 -->     
             <function-class>cn.nicecoder.util.UFunction</function-class>     
             <function-signature>     
                java.lang.String formatDate(java.lang.String)     
             </function-signature>     
             <example>${myTag:formatDate(str)}</example><!-- 例如 -->     
         </function>
    </taglib>    
  2.    創建類,創建方法
    public class UFunction {
    	/**
    	 * 轉換格式"年-月-日"
    	 * @param dateTime
    	 * @return
    	 */
    	public static String formatDate(String dateTime){
    		if(StringUtil.isNotEmpty(dateTime)){
    			return dateTime.substring(0,4) + "-" +dateTime.substring(4,6) + "-" + dateTime.substring(6,8); 
    		}
    		return dateTime;
    	}
    	
    }
  3.    調用方式,jsp裏面調用如下
    <%@ taglib uri="/WEB-INF/mytag.tld" prefix="myTag" %> //頂部添加
  4. <p class="p1">${myTag:formatDate(news.pudate)} - <span style="color: #20B2AA;">${news.type}</span> - ${news.author} - 閱${news.click}</p>

 

 

 

詳情頁

詳情頁和下面的管理員頁面都採用了我最近發現的一個好用的UI框架layui,這個框架有自己的社區,而且持續更新中,感興趣的可以百度layui。拋棄了在我看來只適合做後端的bootstrap。提供了發表評論點贊評論功能。評論評論點贊文章功能也有預留,type傳值不同罷了,但是ui要稍作修改,暫時還沒想好,後續可能會加上。評論的頭像顯示,再加入用戶表之後也可以完善進去。

 

  • layui富文本編輯器,功能不是很強,但是我更看中它的簡潔和外觀,鵝且持續更新中,用法見官網。
  • 錨點定位,滑下來再滑上去手會很痛。使用起來很簡單。
    <a name="mao"></a>//點擊下面的a標籤會跳轉到這裏
    <a href="#mao" ><i class="layui-icon layui-icon-face-smile"></i></a>//圖中的top箭頭
  • ajax異步提交評論
    function discuss(type, id){
    	$("#dis-btn").attr("disabled","true");
    	var content = layedit.getContent(index);
    	$.ajax({
    		dataType:'json',
    		data	:{'content':content, 'type':type, 'id':id},
    		url		:"coreServlet?bizCode=5",
    		async 	: true,
    		success	:function(data){
    			location.href = "coreServlet?bizCode=4&id="+ id;
    		}
    	});
    }
  • 獲取請求的IP得到IP的地區信息,這兩個就從別的地方借來用用,這裏記錄一下,有點長但是很好用。
    public class IPUtil {
    	public static String getIpAddress(HttpServletRequest request) {   
    	    String ip = request.getHeader("x-forwarded-for");   
    	    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {   
    	      ip = request.getHeader("Proxy-Client-IP");   
    	    }   
    	    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {   
    	      ip = request.getHeader("WL-Proxy-Client-IP");   
    	    }   
    	    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {   
    	      ip = request.getHeader("HTTP_CLIENT_IP");   
    	    }   
    	    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {   
    	      ip = request.getHeader("HTTP_X_FORWARDED_FOR");   
    	    }   
    	    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {   
    	      ip = request.getRemoteAddr();   
    	    }   
    	    return ip;   
    	  }   
    }
    public class AddressUtil{   
    	 /** 
    	  * 
    	  * @param content 
    	  *            請求的參數 格式爲:name=xxx&pwd=xxx 
    	  * @param encoding 
    	  *            服務器端請求編碼。如GBK,UTF-8等 
    	  * @return 
    	  * @throws UnsupportedEncodingException 
    	  */  
    	 public static String getAddresses(String content, String encodingString)throws UnsupportedEncodingException {  
    		// 這裏調用pconline的接口  
    		String urlStr = "http://ip.taobao.com/service/getIpInfo.php";  
    		// 從http://whois.pconline.com.cn取得IP所在的省市區信息  
    		String returnStr = getResult(urlStr, content, encodingString);  
    		if (returnStr != null) {  
    			 // 處理返回的省市區信息  
    			 String[] temp = returnStr.split(",");  
    			 if(temp.length<3){  
    				 return "0";//無效IP,局域網測試  
    		}  
    	    String region = (temp[5].split(":"))[1].replaceAll("\"", "");  
    	    region = decodeUnicode(region);// 省份  
    	    
    		String country = "";  
    		String area = "";  
    		// String region = "";  
    		String city = "";  
    		String county = "";  
    		String isp = "";  
    		for (int i = 0; i < temp.length; i++) {  
    		    switch (i) {  
    		    case 1:  
    		        country = (temp[i].split(":"))[2].replaceAll("\"", "");  
    		        country = decodeUnicode(country);// 國家  
    		        break;  
    		        case 3:  
    		            area = (temp[i].split(":"))[1].replaceAll("\"", "");  
    		            area = decodeUnicode(area);// 地區   
    		        break;  
    		        case 5:  
    		            region = (temp[i].split(":"))[1].replaceAll("\"", "");  
    		            region = decodeUnicode(region);// 省份   
    		        break;   
    		        case 7:  
    		            city = (temp[i].split(":"))[1].replaceAll("\"", "");  
    		            city = decodeUnicode(city);// 市區  
    		        break;   
    		        case 9:  
    		                county = (temp[i].split(":"))[1].replaceAll("\"", "");  
    		                county = decodeUnicode(county);// 地區   
    		        break;  
    		        case 11:  
    		            isp = (temp[i].split(":"))[1].replaceAll("\"", "");  
    		            isp = decodeUnicode(isp); // ISP公司  
    		        break;  
    		    }  
    		}  
    	    return region;  
    		}  
    		return null;  
    	 }  
     
    	 /** 
    	  * @param urlStr 
    	  *            請求的地址 
    	  * @param content 
    	  *            請求的參數 格式爲:name=xxx&pwd=xxx 
    	  * @param encoding 
    	  *            服務器端請求編碼。如GBK,UTF-8等 
    	  * @return 
    	  */  
    	 private static String getResult(String urlStr, String content, String encoding) {  
    		URL url = null;  
    		HttpURLConnection connection = null;  
    		try {  
    			url = new URL(urlStr);  
    			connection = (HttpURLConnection) url.openConnection();// 新建連接實例  
    			connection.setConnectTimeout(2000);// 設置連接超時時間,單位毫秒  
    			connection.setReadTimeout(2000);// 設置讀取數據超時時間,單位毫秒  
    			connection.setDoOutput(true);// 是否打開輸出流 true|false  
    			connection.setDoInput(true);// 是否打開輸入流true|false  
    			connection.setRequestMethod("POST");// 提交方法POST|GET  
    			connection.setUseCaches(false);// 是否緩存true|false  
    			connection.connect();// 打開連接端口  
    			DataOutputStream out = new DataOutputStream(connection.getOutputStream());// 打開輸出流往對端服務器寫數據  
    			out.writeBytes(content);// 寫數據,也就是提交你的表單 name=xxx&pwd=xxx  
    			out.flush();// 刷新  
    			out.close();// 關閉輸出流  
    			BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), encoding));// 往對端寫完數據對端服務器返回數據  
    			// ,以BufferedReader流來讀取  
    			StringBuffer buffer = new StringBuffer();  
    			String line = "";  
    			while ((line = reader.readLine()) != null) {  
    				  buffer.append(line);  
    			}  
    			reader.close();  
    			return buffer.toString();  
    	  	} catch (IOException e) {  
    	  		e.printStackTrace();  
    	  	} finally {  
    	  		if (connection != null) {  
    	  			connection.disconnect();// 關閉連接  
    	  		}  
    	  	}  
    		return null;  
    	 }  
    	 /** 
    	  * unicode 轉換成 中文 
    	  * 
    	  * @author fanhui 2007-3-15 
    	  * @param theString 
    	  * @return 
    	  */  
    	public static String decodeUnicode(String theString) {
    		char aChar;
    		int len = theString.length();
    		StringBuffer outBuffer = new StringBuffer(len);
    		for (int x = 0; x < len;) {
    			aChar = theString.charAt(x++);
    			if (aChar == '\\') {
    				aChar = theString.charAt(x++);
    				if (aChar == 'u') {
    					int value = 0;
    					for (int i = 0; i < 4; i++) {
    						aChar = theString.charAt(x++);
    						switch (aChar) {
    						case '0':
    						case '1':
    						case '2':
    						case '3':
    						case '4':
    						case '5':
    						case '6':
    						case '7':
    						case '8':
    						case '9':
    							value = (value << 4) + aChar - '0';
    							break;
    						case 'a':
    						case 'b':
    						case 'c':
    						case 'd':
    						case 'e':
    						case 'f':
    							value = (value << 4) + 10 + aChar - 'a';
    							break;
    						case 'A':
    						case 'B':
    						case 'C':
    						case 'D':
    						case 'E':
    						case 'F':
    							value = (value << 4) + 10 + aChar - 'A';
    							break;
    						default:
    							throw new IllegalArgumentException(
    									"Malformed      encoding.");
    						}
    					}
    					outBuffer.append((char) value);
    				} else {
    					if (aChar == 't') {
    						aChar = '\t';
    					} else if (aChar == 'r') {
    						aChar = '\r';
    					} else if (aChar == 'n') {
    						aChar = '\n';
    					} else if (aChar == 'f') {
    						aChar = '\f';
    					}
    					outBuffer.append(aChar);
    				}
    			} else {
    				outBuffer.append(aChar);
    			}
    		}
    		return outBuffer.toString();
    	}
    
    	// 測試
    	public static void main(String[] args) {
    		AddressUtil addressUtils = new AddressUtil();
    		String ip = "0:0:0:0:0:0:0:1";
    		String address = "";
    		try {
    			address = addressUtils.getAddresses("ip=" + ip, "utf-8");
    		} catch (UnsupportedEncodingException e) {
    			e.printStackTrace();
    		}
    		System.out.println(address);
    	}
    }

 

 

管理員

管理員頁面依然採用的layui,實現了對新聞的發佈編輯詳情刪除。

 

  • 點擊箭頭分頁和首頁採用的同一個js方法,傳的參數不同。
  • 類型轉義可做成數據字典,通過自定義jstl標籤進行轉義顯示。

 

  • 上傳圖片,點擊上傳圖片按鈕和文章中插入圖片採用同一個接口。採用的servlet3.0。好處就是寫servlet不用配置web.xml,可以像springMVC一樣使用註解。
  1. @WebServlet(name="imageUpload", urlPatterns="/imageUpload") 替代web.xml配置方式。
  2. @MultipartConfig  提供HttpServletRequest對文件上傳的支持。通過Part p = req.getPart("name");name是input標籤的name,如果name是不確定的,那麼久用下面這種獲取集合的方式獲取到Part集合,再遍歷之。通過下列一系列操作就可以把本地文件、圖片上傳到服務器。然後就可以被頁面引用啦。
  3. 圖片壓縮是必要的,如果上傳的圖片過大,不僅佔網速,佔空間,在顯示的時候也會出現問題,img會撐破div跑到外面去。後端處理方式通過Thumbnails這個jar包提供一些方法進行壓縮,可以判斷文件大小,也可以判斷寬高,我採用的是寬高。同款jar包下載就在我的資源

        前端處理方式(發佈新聞的時候,我是通過複製別的地方的新聞,圖片自然就是引用的網上的地址,沒有經過後臺上傳。沒         有被壓縮,顯示會出問題。解決方法:img {max-width:762px;overflow:hidden;})

package cn.nicecoder.servlet;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

import net.coobird.thumbnailator.Thumbnails;
import net.sf.json.JSONObject;

/**
 * 上傳文件servlet
 *-------------------------------
 * @author longtian
 * @date 2018年4月23日下午11:09:00
 * @description nicecoder.cn
 *-------------------------------
 */
@WebServlet(name="imageUpload", urlPatterns="/imageUpload")  
@MultipartConfig  
public class UploadImageServlet extends HttpServlet {
	
	private static final long serialVersionUID = 1L;  

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		super.doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		  req.setCharacterEncoding("UTF-8");  
		  Collection<Part> parts = req.getParts(); 
		  
		  JSONObject result = new JSONObject();
		  //Part p = req.getPart("name");
		  for (Part part : parts) {
			  String disposition = part.getHeader("content-disposition");  
		      System.out.println("文件描述:" + disposition);  
		      
		      //文件名,文件類型,文件大小
		      String fileName = disposition.substring(disposition.lastIndexOf("=")+2, disposition.length()-1);  
		      String fileType = part.getContentType();  
		      long fileSize = part.getSize();  
		      System.out.println("fileName: " + fileName);  
		      System.out.println("fileType: " + fileType);  
		      System.out.println("fileSize: " + fileSize);  
		      
		      //1.服務器保存文件路徑
		      String uploadPath = this.getServletConfig().getServletContext().getRealPath("/");
		      //2.文件夾按日期分類
		      String folder = new SimpleDateFormat("yyyyMMdd").format(new Date());
		      //3.拼接文件名
		      if(!new File(uploadPath + File.separator + folder).exists()) {
		    	  	new File(uploadPath + File.separator + folder).mkdirs();
		      }
		      //重命名並寫入文件
		      fileName = new SimpleDateFormat("yyyyMMdd_HHmmSS").format(new Date()) + fileName.subSequence(fileName.indexOf("."), fileName.length());
		      part.write(uploadPath  + folder + File.separator + fileName);
		      
		      //返回存儲地址
		      String src = uploadPath + folder + File.separator + fileName;
		      BufferedImage bufferedImage = ImageIO.read(new File(src));   
		      int width = bufferedImage.getWidth(); 
		      int height = bufferedImage.getHeight(); 
		      
		      //圖片過大的壓縮一下
		      if(width > 762){
		    	  double scale = new BigDecimal((float)762/width).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();  
		    	  Thumbnails.of(src).size(762,(int) (height * scale)).keepAspectRatio(false).toFile(src);  
		      }
		      
		      result.put("code", 0);
		      result.put("msg", "ok");
		      JSONObject subObject = new JSONObject();
		      subObject.put("src", folder + File.separator + fileName );
		      subObject.put("title", fileName);
		      result.put("data", subObject);

		      /*適應layui,所以返回如下格式{
		    	  "code": 0 //0表示成功,其它失敗
		    	  ,"msg": "" //提示信息 //一般上傳失敗後返回
		    	  ,"data": {
		    	    "src": "圖片路徑"
		    	    ,"title": "圖片名稱" //可選
		    	  }
		      }*/
		  }
		  PrintWriter wp = resp.getWriter();
	      wp.write(result.toString());
	      wp.close();
	}

}

 

 

 

 

其他頁面

管理員登錄頁面權限頁面,後期可能會加404頁面,這裏就一筆帶過

 

  • 管理員登錄,管理員界面通關口令通過微信公衆號【在相思樹下】,回覆“1”獲取。這樣做是防止亂搞,非誠勿擾。公衆號也可能會突然分享一波源碼的鏈接,平時不會胡亂推送,可以放心關注啦~。

 

  • 禁止訪問頁面,登錄密碼錯誤或者session過期都會跳到此頁面。

                

 

 

數據庫設計

 

系統共用了四張表,news<新聞表>,newsclass<新聞類別>,discuss<評論表>,agree<點贊表>

 

news表
類型 長度 備註
id int 10 序號
img varchar 100 封面
title varchar 50 標題
content blob 0 內容
type varchar 10 類型
author varchar 50 作者
pudate varchar 50 修改時間
click varchar 20 點擊量

 

discuss表
類型 長度 備註
id int 10 序號
type varchar 10 類型
discussid varchar 10 評論內容編號
content blob 0 內容
userid varchar 50 作者
pudate varchar 50 修改時間
agree varchar 20 點贊量

 

agree表
類型 長度 備註
id int 10 序號
type varchar 10 類型
agreeid varchar 10 點贊內容編號
userid varchar 50 作者
pudate varchar 50 修改時間

 

newsclass表
類型 長度 備註
id int 11 序號
clsname varchar 20 類型名

 

胡亂寫了一堆,可能有的朋友對該項目的源碼已經產生了一丟丟的興趣。那麼下面將放出源碼的獲取方式。雖然是個小項目,但是也投入了一定的精力,所以肯定不能無償獲取哈,希望能夠理解。同時項目中仍有許多不足之處,也請多多批評指正。

 

方式一:CSDN資源下載鏈接,此乃土豪獲取方式,僅需揮灑區區5個積分,便能立馬將文中所述同款源碼一波帶走,簡單而又粗暴。

方式二:通過公衆號【在相思樹下】,回覆“簽到”二字連續簽到3天,亦可獲得同款源碼下載鏈接。而且後期有一些小項目的源碼也能第一時間獲取得到。敬請關注。有的朋友在公衆號上私信我,說很着急,想立即獲得源碼的,請用方式一。說什麼也沒用,不聽~不聽~

公衆號的回覆是機器人回覆,我不一定能夠實時看見。BUG肯定是有的,有什麼問題先自行研究,如果實在不行就在下面留言,或者私信,有時候回覆較慢,請見諒。

2018-8-21 公衆號故障中。。。

附:鏈接: https://pan.baidu.com/s/1i5Ck80oY4rU7Y9cWxEaDuQ 密碼: v6cm 包含表結構和數據。圖片資源找不到了,自行修改。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章