文章目录
servlet实现文件上传
后台逻辑步骤:
- 文件真实的上传路径,把用户上传的文件写入到我们当前的路径下面
- 设置临时文件,有的文件比较大,不能一次性全部上传到服务器上,因此需要一个临时空间,临时保存用户上传的文件,再把它写入到真实的目录下面
- 设置filename工厂,目的处理临时文件
- 创建servletfileUpload,把临时文件工厂告诉上传处理器
- 监听器,读取文件上传了多少,可以获取读取百分比
- 设置中文乱码
- 设置文件上传限制,最大上传文件值,总文件大小
- 通过上传处理器upload获取包含在request上传的所有文件(一个或者多个)
- 迭代上传的文件,获取文件名称并处理错误,判断文件扩展名是否符合后台所需文件类型,如果不是就删除临时文件并告诉前端文件非法,
- 获取文件输入流,就是用户上传的文件
- 创建一个文件名称(写一个方法),根据基本路径结合文件名称得到新文件的绝对路径
- 通过输出流和缓存空间,把原文件输入流写入到新文件的绝对路径下
- 关闭输入输出流,删除临时文件
servlet内容如下:
package demo;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
public class UploadServlet extends javax.servlet.http.HttpServlet {
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
String errorMessage = "";
//设置文件上传的基本路径
String savePath=this.getServletContext().getRealPath("/uploadFiles");
//设置临时文件路径
String tmpePath = this.getServletContext().getRealPath("/tempFiles");
//判断文件夹是否存在 true:不做处理 false:创建文件夹
File tempfile = new File(tmpePath);
if (!tempfile.exists()){tempfile.mkdir();}//创建临时文件夹}
//创建临时文件工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置缓冲区大小
factory.setSizeThreshold(1024*100);
//设置临时文件路径
factory.setRepository(tempfile);
//创建文件上传处理器
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传进度
/*pBytesRead :正在上传文件的进度(上传文件的进度大小)
* pContentLength:正在上传文件的大小
* pItems:正在读取的文件
*/
ProgressListener progressListener = new ProgressListener() {
@Override
public void update(long pBytesRead, long pContentLength, int pItems) {
System.out.println("正在读取文件:"+pItems);
if (pContentLength==-1){
System.out.println("已读取: "+pBytesRead+"剩余零!");
}else{
System.out.println("文件总大小:"+pContentLength+"已读取:"+pBytesRead);
}
}
};
upload.setProgressListener(progressListener);
//设置文件上传是文件名中文乱码处理
upload.setHeaderEncoding("UTF-8");
//判断提交的数据是否是上传表单的数据
if (!ServletFileUpload.isMultipartContent(request)){
//按照传统的方式读取数据
return;
}
//设置上传单个文件的大小的最大值 单位:字节 1MB
upload.setFileSizeMax(1024*1024);
//设置文件上传总量最大值, 最大值:同时上传的多个文件的大小的最大值的和,目前设置10MB
upload.setSizeMax(1024*1024*10);
try {
//开始文件上传 通过 ServletFileUpload 的 parseRequest(request) 获取为在request中的文件
//使用ServletFileUpload解析器 解析上传(request)的数据,解析结果返回一个List<FileItem>
//集合每一个FileItem都对应一个Form表单的输入项目
List<FileItem> items = upload.parseRequest(request);
//通过迭代器 遍历集合
Iterator<FileItem> iterator = items.iterator();
while (iterator.hasNext()){
//获取每一个FileItem
FileItem item = iterator.next();
//判断当前FileItem是否是一个文件
if (item.isFormField()){
errorMessage="请提交文件";
break;
}else{
//获取文件名称
String filename = item.getName();
if (null==filename || filename.trim()==""){
System.out.println("文件名为空");
}
//截取文件名
filename = filename.substring(filename.lastIndexOf("\\") + 1);
//不同的浏览器 提交的文件的文件名的路径 是存在区别的.获取文件扩展名 aasda.jpg
String fileExtension = filename.substring(filename.lastIndexOf(".") + 1);
if (!validExtension(fileExtension)){
//当前Fileitem 的文件的扩展名 不是我们需要
errorMessage = "上传文件非法";
item.delete();
break;
}
//获取文件输入流
InputStream in = item.getInputStream();
//获取保存文件的名称
String saveFileName = createFileName(filename);
//获取保存文件的路径 //根据基本路径 与 新的文件名称 获取到了 一个新文件的绝对路径
String realFilePaht = createRealFilePath(savePath,saveFileName);
//创建文件输出流
FileOutputStream out = new FileOutputStream(realFilePaht);
//创建缓冲区
byte[] buffer = new byte[1024];
int len = 0;
while ( (len = in.read(buffer)) > 0 ){
//写入文件
out.write(buffer,0,len);
}
in.close();//关闭输入流
out.close();//关闭输出流
item.delete();//删除临时文件
}
}
}catch (FileUploadBase.FileSizeLimitExceededException e) {
errorMessage = "单个文件超出最大值!!!";
e.printStackTrace();
} catch (FileUploadBase.SizeLimitExceededException e) {
errorMessage = "总文件超出最大值!!!";
e.printStackTrace();
}catch (FileUploadException e) {
errorMessage = "文件上传失败!!!";
e.printStackTrace();
}
//保存错误信息
request.setAttribute("errorMessage",errorMessage);
//转发重定向
request.getRequestDispatcher("fileUpload.jsp").forward(request,response);
}
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
doPost(request,response);
}
/**
* 用于 验证上传文件的类型 是否是我们需要的
* 用于过滤 不需要的 "jpg","txt","doc","pdf"}
*
* @param fileExtension
* @return
*/
private boolean validExtension(String fileExtension) {
String[] exts = {"jpg", "txt", "doc", "pdf"};
for (int i = 0; i < exts.length; i++) {
if (fileExtension.equals(exts[i])) {
return true;
}
}
return false;
}
/**
* 用于 重命名 文件
*
* @param fileName
* @return
*/
private String createFileName(String fileName) {
return UUID.randomUUID().toString() + "_" + fileName;
}
/**
* 根据基本路径 和 文件名称 生成真实的文件 路径 :基本路径 年|月|filename
*
* @param basePath
* @param fileName
* @return
*/
private String createRealFilePath(String basePath, String fileName) {
//获取年 月
Calendar today = Calendar.getInstance();
String year = String.valueOf(today.get(Calendar.YEAR));
String month = String.valueOf(today.get(Calendar.MONTH) + 1);
// File.separator 根据系统自动创建 \
String upPath = basePath + File.separator + year + File.separator + month + File.separator;
File uploadFolder = new File(upPath);
if(!uploadFolder.exists()){
uploadFolder.mkdirs();
}
return upPath+fileName;
}
}
jsp文件如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上传</title>
</head>
<body>
<%--文件上传必备条件 1、表单必须为post method="post" 2、必须为数据表单 enctype="multipart/form-data"--%>
<form action="${pageContext.request.contextPath}/uploadServlet" method="post" enctype="multipart/form-data">
<input type="file" name="file"/>
<input type="submit"/>
</form>
<p style="color: red;">${requestScope.errorMessage}</p>
</body>
</html>
servlet实现Ajax异步请求
Ajax:部分刷新,通过servlet演示Ajax的应用:页面传给给servlet参数,servlet经过处理后返回给Ajax,Ajax部分刷新页面的内容。
步骤如下:
- demo下创建一个新的servlet起名为AjaxServlet,在web.xml中关联这个AjaxServlet
<servlet>
<servlet-name>AjaxServlet</servlet-name>
<servlet-class>demo.AjaxServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AjaxServlet</servlet-name>
<url-pattern>/AjaxServlet</url-pattern>
</servlet-mapping>
- servlet内容:
注意:servlet把值返回给Ajax回调函数的data处。
用户点击页面,访问servlet,servlet获取传入的参数键,通过response的写入方法返回给Ajax的回调函数,Ajax再置换页面的内容但不刷新整个页面
package demo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "AjaxServlet")
public class AjaxServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
String name = request.getParameter("name"); //获取页面传来的参数date
String age = request.getParameter("age");
//将内容发送页面的ajax的回调函数中data处
response.getWriter().write("测试:姓名:"+name+"年龄:"+age);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
- Ajax.jsp
<%--
Created by IntelliJ IDEA.
User: scq
Date: 2020/11/21
Time: 14:20
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>异步刷新页面内容</title>
</head>
<body>
<h1>测试:原有数据</h1>
<button id="butA">点击刷新</button>
<%--ajax需要javascript--%>
<script type="text/javascript" src="${pageContext.request.contextPath}/statics/js/jquery-3.4.1.js"></script>
<script type="text/javascript">
$(function () {
$("#butA").click(function () {
$ajax({
url:"${pageContext.request.contextPath}/AjaxServlet", /*请求路径*/
type:"post",/*请求的方式*/
dataType:"text",/*返回结果的类型*/
data:{name:"scq",age:12},/*传递给serlvet的参数*/
success:function(data){/*data为后台返回来的参数,成功后*/
$("h1").html(data)
},
error:function () {
alert("请求失败")
}
})
}
})
})
</script>
</body>
</html>
Ajax实现年级的增删改查
什么是JSON?
JSON指的是JavaScript对象表示法(JavaScript Object Notation)
JSON是轻量级的文本数据交换格式
JSON 独立于语言:JSON使用JavaScript语法来描述数据对象,但是JSON仍然独立于语言和平台.
JSON解析器和JSON库支持多种不同的编程语言。(PHP JSP .NET等)都支持JSON
JSON具有自我描述性,更容易理解
JSON是存储和交换信息的语法,类似于XML
JSON比XML更小 更快 更易解析
JSON的值 可以有 :数字 字符串 逻辑值(true false)数组 对象 集合 null
什么是Ajax?
Ajax = Asynchronous JavaScript and XML (异步的JavaScript 和XML)
Ajax 不是新的编程语言,而是一种使用现有的标准的新方法
Ajax最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容
Ajax 不需要任何的浏览器插件,但是需要用户允许JavaScript在浏览器运行
步骤如下:
- entity层:创建年级的实体,年级名称和年级ID
- Dao层
- service层
- servlet:后台通过
response.getWriter().write
返回ajax请求给前台
package Servlet;
import entity.Grade;
import service.GradeService;
import service.Impl.GradeServiceImpl;
import com.alibaba.fastjson.JSON;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "GradeServlet")
public class GradeServlet extends HttpServlet {
private GradeService gradeService=new GradeServiceImpl();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
String index = request.getParameter("index");
switch (index){
case "1":
query(request,response);
break;
case "2":
insert(request,response);
break;
case "3":
delete(request,response);
break;
case "4":
update(request,response);
break;
case "5":
queryGradeId(request,response);
break;
}
}
private void queryGradeId(HttpServletRequest request, HttpServletResponse response) throws IOException {
String gradeId = request.getParameter("gradeId");
Grade grade = gradeService.queryGrade_Id(gradeId);
response.getWriter().write(JSON.toJSONString(grade));
}
private void update(HttpServletRequest request, HttpServletResponse response) throws IOException {
Grade grade=new Grade(Integer.parseInt(request.getParameter("gradeId")),request.getParameter("gradeName"));
int row = gradeService.updateGrade(grade);
response.getWriter().write(row+"");
}
private void delete(HttpServletRequest request, HttpServletResponse response) throws IOException {
String gradeId = request.getParameter("gradeId");
int row = gradeService.deleteGrade(gradeId);
response.getWriter().write(row+"");
}
private void insert(HttpServletRequest request, HttpServletResponse response) throws IOException {
Grade grade=new Grade(request.getParameter("gradeName"));
int row = gradeService.addGrade(grade);
response.getWriter().write(row+"");
}
private void query(HttpServletRequest request, HttpServletResponse response) throws IOException {
//查询到所有年级 通过fastjson工具将 集合json化
//获取用户输入的年级名
String gradeName = request.getParameter("gradeName") ==null ? "" : request.getParameter("gradeName");
response.getWriter().write(JSON.toJSONString(gradeService.queryGrade(gradeName)));
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
- jsp:将用户在前台输入的内容当作参数通过Ajax(页面发起请求 动态去问后台要值)传入后台,后台返回给前台的值前台遍历展示
<%--
Created by IntelliJ IDEA.
User: scq
Date: 2020/11/25
Time: 11:21
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>年级信息</title>
</head>
<body>
<input type="text" id="gradeName">
<button onclick="queryGradeInfo()">查询年级</button>
<ul id="gradeList">
</ul>
<P>
修改:<input type="text" id="upGrade"/><input type="hidden" id="hidGradeId">
<button onclick="updateGrade()">修改</button>
</P>
<P>
增加:<input type="text" id="addgrade">
<button onclick="addGrade()">增加</button>
</P>
<script type="text/javascript" src="${pageContext.request.contextPath}/statics/js/jquery-3.4.1.js"></script>
<script>
<%-- 什么时候执行:当页面加载完之后执行此函数--%>
function queryGradeInfo() {
var $gradeName=$("#gradeName");
$.ajax({
url:"${pageContext.request.contextPath}/GradeServlet",
type:"post",
dataType:"json",
//将用户输入的内容传入后台
data:{index:1,gradeName:$gradeName.val()},
success:function (data) {
$("ul li").remove();
$.each(data,function (index,value) {
var htmls="<li>"+value.gradeName+"<a href='javascript:deleteGrade("+value.gradeId+")'>删除</a>|<a href='javascript:queryGradeId("+value.gradeId+")'>修改</a> </li>";
$("#gradeList").append(htmls);
})
},
error:function(){
alert("请求失败");
}
});
}
function addGrade() {
var gradeName=$("#addgrade").val();
$.ajax({
url: "${pageContext.request.contextPath}/GradeServlet", /*请求路径*/
type: "post",/*请求的方式*/
dataType: "text",
data:{index:2, gradeName: gradeName},
success:function (data) {
if (data=='1'){
queryGradeInfo();
alert("添加成功");
}
},
error:function () {
alert("请求失败")
}
})
}
function queryGradeId(gradeId) {
//要改先查
$.ajax({
url: "${pageContext.request.contextPath}/GradeServlet", /*请求路径*/
type: "post",/*请求的方式*/
dataType: "json",
data:{index:5,gradeId:gradeId},
success:function (data) {
$("#upGrade").val(data.gradeName);
//填充隐藏域 用于修改
$("#hidGradeId").val(data.gradeId);
},
error:function () {
alert("请求失败")
}
})
}
function deleteGrade(gradeId) {
if (confirm("是否删除?")) {
$.ajax({
url: "${pageContext.request.contextPath}/GradeServlet", /*请求路径*/
type: "post",/*请求的方式*/
dataType: "text",/*返回结果的类型*/
data: {index: 3, gradeId: gradeId},/*传递的参数*/
success: function (data) {/*成功后*/
if (data == '1') {
queryGradeInfo();
alert("删除成功");
}
},
error: function () {/*失败后*/
alert("请求失败");
}
});
}
}
function updateGrade() {
if (confirm("是否修改?")){
var gradeName=$("#upGrade").val();
var gradeId=$("#hidGradeId").val();
$.ajax({
url: "${pageContext.request.contextPath}/GradeServlet", /*请求路径*/
type: "post",/*请求的方式*/
dataType: "text",
data:{index:4,gradeId:gradeId,gradeName:gradeName},
success:function (data) {
if (data=='1'){
//调用查询 回填所有数据
queryGradeInfo();
alert("修改成功")
}
},
error:function () {
alert("请求失败")
}
})
}
}
</script>
</body>
</html>
报错总结:
- 404错误:项目文件的放置一定要准确,lib依赖jar包要放在web-INFO中,web目录下不要随意放置文件,jsp文件要放在web下,不可以放在web-INFO下
- 当点击页面没有期望的值时要去看啊可能servlet中给Ajax的返回值:1、是否成功返回,如果alert出来为Undefined,那很可能是没有在数据库查询到值,就要去看看实体层的属性值与后台接收传值到数据库查询并通过JSON将实体层对象返回到前台,前台通过键值对来获取的值是否一致;servlet返回给jsp的类型与jsp接收值的类型也要一致,否则无法进入下一步
servlet项目:新闻发布系统
功能一:主页新闻的分页查询并显示
分页的特殊技术: ajax访问后台进行分页获取
逻辑步骤:
先请求servlet 将分页工具类带到页面上,展示第一页,然后页面根据分页工具类再请求servlet,获取上一页/下一页的数据
servlet中:
- 如果是第一次访问页面,默认当前页为1,分页工具类中设置当前页,和每页显示条数,查询新闻总数,
调用业务层的方法查询到新闻并将新闻集合保存到分页工具类中,将分页工具类转换为JSON格式,write到页面中,页面就可以使用ajax来部分刷新页面。
JSP页面中:
- 写一个通过ajax访问servlet获取新闻数据显示到主页的函数queryNews(pageNum)
传入参数为当前页,第一次访问页面当前页为1,通过ajax向servlet获取新闻数据,然后通过servlet返回的JSON格式的分页工具类获取里面的新闻对象,使用jqery来替换部分页面的内容,当点击下一页时,会访问这个函数并通过servlet返回的JSON格式的分页工具类的当前页值作为函数的参数再返回到servlet中获取新一页的新闻数据显示到页面上
功能二:新闻的添加与修改
首先从查询开始
-
新闻的查询
servlet:新闻后台显示的方法
jsp页面:点击编辑新闻的时候访问servlet,注意,用户登陆进入后台时一开始是没有新闻展示的,此时用户登陆成功后需要先跳转到servlet,获取数据
-
新闻的添加:
- 点击添加新闻跳转到news_add.jsp页面,进入添加页面后,会显示需要选择的新闻分类主题,因此需要查询所有主题填充下拉选项,进入到主题servlet写一个返回JSON格式的Ajax请求的所有主题方法,返回到新闻添加页面前台发起ajax请求,来获取数据填充页面。
- Dao层写一个通过新闻对象,添加一条新闻的方法,注意没有修改时间属性,创建时间属性写为
NOW()
-
新闻的添加之文件上传
- 将文件上传方法嵌入NewsServlet的addNews()方法中, 由于用户在添加新闻时,提交新闻摘要、作者、…文件等,request是无法通过
getParamer()
来获取用户输入的指定内容的,必须要通过迭代器Fileitem来读取,需要判断一些不是文件的数据,非文件数据通过item.getString()
获取用户输入的值,并保存到news对象中;如果是文件的话就保存这个文件的名称到news对象中,最后调用业务层添加这个新闻对象,执行查询总新闻的方法进行页面展示
- 将文件上传方法嵌入NewsServlet的addNews()方法中, 由于用户在添加新闻时,提交新闻摘要、作者、…文件等,request是无法通过
-
新闻的修改
- 需要对于在数据库中新闻对象的图片是否存在做出判断,每一次修改新闻也并不需要上传图片,如果数据库存在该新闻对应的图片就不需要上传,因此jsp页面处增加一个隐藏域的输入标签,value为上传图片的路径,每一次点击修改都查看该隐藏域的value的长度是否为0,为0表示该新闻对象没有图片,可以上传,否则就将新闻对象的图片地址属性值保存为原新闻对象的图片地址值。
-
新闻的点击展示与自带评论
- 当用户点击页面展示的新闻时可以查看该新闻的具体内容,和评论。当用户点击新闻时访问后台传入当前新闻的nid,后台servlet查询到该新闻携带新闻对象跳转到展示新闻的页面
- 自带评论: 创建评论实体层、Dao层、业务层,根据新闻nid查询当前新闻下所有的评论 在查询到该新闻携带新闻对象和评论集合一起跳转到展示新闻的页面;
- 评论的发布: 需要获取当前新闻的nid,点击提交评论时,访问newsServlet中指定的方法,通过标签name属性获取用户输入的内容保存到评论对象中,添加到数据库里,并返回到新闻展示页面。
功能三:侧边栏新闻的查询并展示
-
entity实体层按照新闻属性创建News类、话题属性创建Topics类,根据数据库的News表的设计表来获取属性
-
Dao层
接口处写按照分类编号查询新闻的方法,如果分类编号为空就显示所有新闻。
实现类实现此方法返回一个装有新闻对象的集合List
注意:实体层的新闻类News属性是按照数据库News表的设计表中的属性顺序填写并依照此来生成的有参构造方法,在方法中按照数据库News表的设计表中的属性顺序查询列,那么获取查询结果也是按照数据库News表的设计表中的属性顺序来获取,保存到新闻类对象News实例化这个对象时,属性的添加也要按照数据库News表的设计表中的属性顺序。
实现类方法如下:
package Dao.Impl;
import Dao.NewsDao;
import entity.News;
import utils.BaseDao;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class NewsDaoImpl extends BaseDao implements NewsDao {
@Override
public List<News> queryNews(String ntid) {
StringBuffer sql = new StringBuffer();
//查询按照News表的属性顺序选择列,获取信息时也按照News表的属性顺序来获取
sql.append(" select nid,ntid ");
sql.append(" ntitle,nauthor ");
sql.append(" ncreateDate,npicPath ");
sql.append(" ncontent,nmodifyDate ");
sql.append(" nsummary from news ");
sql.append(" where 1=1 ");
if (null!=ntid&& ntid!="")
sql.append(" and ntid="+ntid);
Connection connection = getConnection();
ResultSet resultSet = executeQuery(connection, sql.toString());
List<News> newsList = new ArrayList<>();
try {
while (resultSet.next()){
newsList.add(new News(
resultSet.getInt("nid"),
resultSet.getInt("ntid"),
resultSet.getString("ntitle"),
resultSet.getString("nauthor"),
resultSet.getString("ncreateDate"),
resultSet.getString("npicPath"),
resultSet.getString("ncontent"),
resultSet.getString("nmodifyDate"),
resultSet.getString("nsummary")));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
closeAll(connection,null,resultSet);
}
return newsList;
}
}
-
utils放连接数据库的BaseDao,并将配置文件中连接的数据库名修改
-
service层
接口创建查询方法,实现类调用Dao层的查询方法。
实现类代码如下:
package service.impl;
import Dao.Impl.NewsDaoImpl;
import Dao.NewsDao;
import entity.News;
import service.NewsService;
import java.util.List;
public class NewsServiceImpl implements NewsService {
private NewsDao newsDao=new NewsDaoImpl();
@Override
public List<News> queryNews(String ntid) {
return newsDao.queryNews(ntid);
}
}
-
servlet
创建查询新闻的方法,并把查询结果集返回给index.jsp页面。 -
index_sidebar.jsp
- 跳转到主页index.jsp,我们要编辑的页面是index_sidebar.jsp,再加上index.jsp引用了index_sidebar.jsp页面,就会显示出我们编辑的效果。
- url后面只有项目名时默认进入index.jsp页面,此时并没有访问servlet因此不会显示我们在index_sidebar.jsp修改的内容,因此我们要在index.jsp页面进行判断,当加载了servlet查询新闻后,返回给index.jsp的参数(查询结果集)是非空的,因此只要返回给index.jsp的参数为空,我们就去请求当前的servlet并传递要servlet查询新闻方法对应的index参数,让servlet将查询结果返回index.jsp来获取数据,这样index.jsp就会显示修改的内容,
功能四:用户的登录登出
- 将用户的信息提交时,前台先验证用户输入的内容是否规范,规范再提交到后台查询此用户是否登陆成功,成功就将用户保存到session中,跳转到用户界面
- 用户的登出就是将session初始化并返回index页面
功能五:admin登陆成功后添加主题
-
entity层
topic类 -
Dao层
查询数据库展示所有主题;
对主题的增删改查;
如果添加主题时要判断不能与原有主题名称重复,因此需要一个方法:通过主题名称查询主题 -
service层
实现Dao层的方法 -
servlet层
主要理解添加主题时对主题是否与原有主题重复的判断:
servlet写一个查询添加的主题名称在数据库中的count(1)的值,count=0表示可以添加;前台在用户提交表单的时候使用验证函数,此验证函数包含ajax请求判断是否重复的函数,验证函数全部通过就可以提交表单,表单的提交访问servlet中添加主题的函数,并跳转到编辑主题页面显示所有主题,如果验证函数不通过就alert错误并停留在当前添加主题页面 -
jsp
注意一:form表单提交事件时,在form表单后使用onsubmit="return check()"
;此方法不保险,可以在点击提交按钮时触发函数
<input type="button" onclick="check()" value="提交" class="opt_sub" />
,check()
中所有验证判断通过就提交当前表单
注意二:Jqery执行顺序的问题。当一个表单提交事件函数使用if语句来获取ajax访问后台的函数的返回值时,页面会将if的判断条件认为true直接先进入if语句里面,再去执行ajax访问后台的函数,这样处理的结果会造成无论ajax访问后台的函数返回值为什么,表单提交事件函数都不会当if的判断为false时进行下一步选择提交表单。
改进:将表单的提交写入ajax函数成功的内容里面,页面点击事件为访问ajax函数
功能六:admin登陆成功添加主题后的删除修改
-
删除功能要实现2个地方:页面内容的删除、ajax访问数据库删除主题
页面内容的删除使用动态删除方法,将主题所在的li标签设置id与主题对象的id拼接,当删除一个主题时就把这个li也清空掉;
Dao层
service层
servlet层返回ajax请求需要的值
jsp页面当用户点击删除时发起ajax请求,删除数据库的数据并清除页面的主题内容 -
修改功能:
一、要改先查,点击修改时要向后台servlet传入当前主题的id参数,查询到当前要修改的这个主题对象传入到修改主题的页面中,修改主题的页面输入框中显示要被修改的主题名称;
二、在修改主题的页面中,点击提交表单按钮时先对用户输入的主题名称进行验证:不可为空,数据库中不可以存在,修改过了不可与旧主题名称相同,验证通过再提交到servlet中,进行数据库中主题的修改。
三、修改过了不可与旧主题名称相同这一逻辑判断,我们需要使用1个隐藏域,input标签获取用户输入的主题名称,一个input隐藏域为传入修改页面的被修改主题名称,2个标签设置id进行值的判断,相同表示用户没有修改。
新闻项目的报错
-
重定向次数过多
sql语句书写有问题:由于serlvet要去查询数据库的内容并将结果返回给jsp页面,jsp页面做了判断,如果从serlvet获取的值为空就去servlet拿值,但是由于sql语句书写有问题就会导致servlet无法获取数据,返回给jsp页面的值为空,那么jsp页面就会再次询问servlet…因此重定向次数过多 -
500 初始化错误 jsp页面的语法书写有问题,检查语法格式
-
uri的问题 标签库导入有问题,找到导入标签库的jsp页面,重新导入,可能是单词拼错
-
页面不显示查询内容:查看servlet返回值与前台接收是否一致;使用ajax访问后台数据看看jsp格式
$.ajax({})
是否正确 -
Jquery版本的问题:表单的提交使用在提交按钮上绑定点击事件,并且提交按钮type为button
-
Mysql错误1452 - Cannot add or update a child row: a foreign key constraint fails 原因及解决方法
添加的外键列与另一个表的唯一索引列(一般是主键)的数据类型不同、设置的外键与另一个表中的唯一索引列(一般是主键)中的值不匹配 ,也就是Dao层sql语句写的有问题,sql语句与参数要对应