项目一总结
day1
构建Maven 工程
src/main/java
src/main/resources
src/test/java
src/test/resources
搭建三层项目环境
1.拷贝页面:src/main/webapp/web-inf/views
2.修改页面为jsp
3.希望访问webapp/web-inf/views/index.jsp 但是访问不了!因为web-inf 只有通过程序访问
4.写一个IndexController
后台管理页面统一存放在WEB-INF文件夹下的system文件夹中,而WEB-INF文件夹是安全目录,浏览器是不能直接访问到WEB-INF中的目录,只能通过服务器转发的方式访问到该目录,要从浏览器中访问到该目录,需要定义一个Controller用于转发
配置文件:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置前缀 -->
<property name="prefix" value="/WEB-INF/system/"></property>
<!-- 配置后缀 -->
<property name="suffix" value=".jsp"></property>
</bean>
IndexController代码:
@Controller
@RequestMapping("/system")
public class IndexController {
@RequestMapping("/index")
public String system(){
return "index";
}
@RequestMapping("/main")
public String main(){
return "main";
}
}
全注解开发
@Controller 控制器
@Service 业务对象
@Repository 持久层对象
@Component 组件
day2
富文本编辑器
<div id="editor">
<p>欢迎使用 <b>wangEditor</b> 富文本编辑器</p>
</div>
<!-- 注意, 只需要引用 JS,无需引用任何 CSS !!!-->
<script type="text/javascript" src="/wangEditor.min.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor = new E('#editor')
// 或者 var editor = new E( document.getElementById('editor') )
editor.create()
</script>
Ajax交互方式
优点:
异步请求,发送请求的同事还可以继续操作页面。页面不销毁;
返回部分数据,减少不必要的数据承传输,介绍网络资源。页面不刷新,而是更新页面部分数据;
同步和异步请求
同步:你先做完我再做,后一步的操作必须要等待前一步操作的结果
异步:各做各的相互不干扰(效率高)
1.AJAX对象本身是浏览器中的一个对象,但在低版本IE中表现为一个ActiveX。所以在使用JavaScript语言进行创建该对象时,需要区分不同的浏览器
2.有时候我们会把XMLHttpRequest对象称为AJAX对象,或异步对象
创建方式1:判断方式
function getXhr(){
var xhr = null;
if(window.XMLHttpRequest){//针对其他浏览器
xhr = new XMLHttpRequest();
}else{//针对低版本的ie浏览器
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
return xhr;
}
day3
分页
分页是我们开发中很常见的功能。试想一下,如果一张表有20万条数据,我们一次读取出来,对整个程序的性能是非常大的负担,而且也要影响到查询的速度。对用户来说,一下看到这么多数据估计也是醉了。
分页有两种:真分页与假分页。
这个只是我们对两种分页方式的取名而已,两种分页方式没有孰优孰劣。他们只是方式与特性不同,于是选择上有不同,咱们B/S结构的软件可能更多的会使用真分页来完成功能。
假分页(前端分页)
比如说现有数据库有300条数据。
它先把300要数据全部读取到我们的内存里面。
Select * from news; -> List<Product> 300条
如果我每页30条,那么我们都从内存里面(List) 里面来读取
好处:翻页快,功能实现简单,只适合小数据量 且不会经常修改的数据
劣势:占用内存大
真分页(后端分页)
比如说现有数据库有300条数据。
如果我每页30条,那么每次到数据库里去读取当前的30条数据
select * from news LIMIT 0,3
select * from news LIMIT 3,3
select * from news LIMIT ?,3
好处:占用内存小
劣势:翻页慢
它查询数据是匀速的
2.2.代码实现
分页对象
public class PageList<T> {
//当前页
private Integer currentPage;
//总页数
private Integer totalPage;
//当前页面显示数据
private Integer pageSize;
//总数据数
private Integer totalData;
//首页
private Integer firstPage=1;
//上一页
private Integer prePage;
//下一页
private Integer nextPage;
//尾页
private Integer lastPage;
//显示的数据
private List<T> list;
……
public PageList(Integer currentPage, Integer pageSize, Integer totalData, List<T> list) {
this.currentPage = currentPage;
this.pageSize = pageSize;
this.totalData = totalData;
this.list = list;
//首页
this.firstPage=1;
//总页数
this.totalPage=this.totalData%this.pageSize==0?this.totalData/this.pageSize:this.totalData/this.pageSize+1;
//上一页
this.prePage=this.currentPage==1?1:this.currentPage-1;
//下一页
this.nextPage=this.currentPage==this.totalPage?this.totalPage:this.currentPage+1;
//尾页
this.lastPage=this.totalPage;
}
}
分页条件对象
public class SqlCondition {
private Integer currentPage=1;
private Integer pageSize=10;
…….
}
DAO代码
public PageList<Images> queryAll(SqlCondition sc) {
String countSql="select count(*) from images";
Integer count = jt.queryForObject(countSql, Integer.class);
String sql="select * from images";
List<Images> list = jt.query(sql, new BeanPropertyRowMapper(Images.class));
PageList<Images> pageList = new PageList<>(sc.getCurrentPage(), sc.getPageSize(), count, list);
System.out.println(pageList);
return pageList;
}
Controller代码
@RequestMapping("/query")
public String query(SqlCondition sc,Model m){
PageList<Images> queryAll = service.queryAll(sc);
m.addAttribute("pageList",queryAll);
return "main";
}
前端页面-数据展示
<c:forEach items="${requestScope.pageList.list }" var="img">
<tr>
<th>#${img.imgid }</th>
<th>${img.storepath }</th>
<th>${img.intro }</th>
<th>
<c:choose>
<c:when test="${img.isenabled }">
<span class="glyphicon glyphicon-ok" aria-hidden="true" />
</c:when>
<c:otherwise>
<span class="glyphicon glyphicon-remove" aria-hidden="true"/>
</c:otherwise>
</c:choose>
</th>
<th>${img.inputdate }</th>
<th><a href="main_edit.html" class="btn-default tableA"><span
class="glyphicon glyphicon-pencil" aria-hidden="true">修改</span></a> <a
href="" class="btn-default tableA"><span
class="glyphicon glyphicon-trash" aria-hidden="true">删除</span></a>
</th>
</tr>
</c:forEach>
前端页面-分页
<ul class="pagination" id="paging">
<li><span>当前第${requestScope.pageList.currentPage }页</span></li>
<li><a href="${pageContext.request.contextPath }/img/query?currentPage=${requestScope.pageList.currentPage }"> <span aria-hidden="true">首页</span></a></li>
<li><a href="${pageContext.request.contextPath }/img/query?currentPage=${requestScope.pageList.prePage }" aria-label="上一页"> <span aria-hidden="true">上一页</span></a></li>
<li></li>
<li><a href="${pageContext.request.contextPath }/img/query?currentPage=${requestScope.pageList.nextPage }" aria-label="下一页"> <span aria-hidden="true">下一页</span></a></li>
<li><a href="${pageContext.request.contextPath }/img/query?currentPage=${requestScope.pageList.lastPage }" aria-label="尾页"> <span aria-hidden="true">尾页</span></a></li>
<li><span>总页数:共${requestScope.pageList.totalPage }页</span> <span>总数据:共${requestScope.pageList.totalData }条</span></li>
</ul>
3.CMS首页数据【高级查询】
一张表中有10000多个客户,我们是让用户从10000多个人中去找,还是根据一些条件(如名称,性别等)过一次过滤查询就找到。
其实完成高级查询,就是拼接Sql(根据不同的条件拼接Sql来实现不同的查询)
高级查询就是拼接Sql.
高级查询就是在查询基础上添加后面的where条件
2 根据不同的情况,where后面的条件都不同的
3 提供的过滤条件越多,我们查询的排列组合也就越多
综上可以看到,我们需要提供相应的查询字段,但是会不会用到,就看客户自己。但是由于这咱排列组合,我们不可能把所有的Sql全部准备好。
因此,咱们必需要能生成动态SQL(说白了就是根据条件来拼接字符串)
怎么拼接呢?用户选择了,这个字段就不为空,当这个字段不为空的时候,我们就在where后的查询加上这个条件过滤
day4 页面静态化
MVC (模型 视图 控制器) 模式,对于动态网页来说,是一种特别流行的模式。 它帮助从开发人员(Java 程序员)中分离出网页设计师(HTML设计师)。设计师无需面对模板中的复杂逻辑, 在没有程序员来修改或重新编译代码时,也可以修改页面的样式。
而FreeMarker最初的设计,是被用来在MVC模式的Web开发框架中生成HTML页面的,它没有被绑定到 Servlet或HTML或任意Web相关的东西上。它也可以用于非Web应用环境中
完成静态化的步骤:
1.导入jar包
* 2.创建一个配置对象 1.传递一个版本
3.设置模板加载路径
4设置一个模板编码
5.获取一个模板对象
6获取一个数据
7生成文件
day5
轮播管理
2.1.文件上传
1.前端页面设置
<form action="${pageContext.request.contextPath }/img/add" enctype="multipart/form-data" method="post">
<div class="form-group">
<label for="fileImg">轮播图上传</label> <input type="file" name="fileImg">
</div>
<div class="form-group">
<label for="isenabled">是否启用:</label> <label class="radio-inline">
<input type="radio" name="isenabled" id="isenabled" value="true"
checked="checked">是
</label> <label class="radio-inline"> <input type="radio"
name="isenabled" id="isenabled" value="false">否
</label>
</div>
<div class="form-group">
<label for="intro">轮播图简述</label>
<div id="intro"></div>
<input type="hidden" id="txtIntro" name="intro" />
</div>
<div class="btn-toolbar" data-role="editor-toolbar"
data-target="#editor">
<a class="btn btn-large" data-edit="bold"><i class="icon-bold"></i></a>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">新增轮播</button>
</div>
</form>
上传文件使用的前端页面,必须按照如下标准:
post提交数据
enctype属性被修改为:multipart/form-data
使用上传文件的file标签
2.配置文件上传
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize">
<value>100000</value>
</property>
<property name="defaultEncoding">
<value>UTF-8</value>
</property>
</bean>
3.代码实现
@RequestMapping(value="/add",method=RequestMethod.POST)
public void add(Images img,HttpServletRequest req) throws Exception{
/**
* 需求:新增上传文件数据,新增成功跳转查询
*/
//获取到上传的文件数据
MultipartFile fileImg = img.getFileImg();
ServletContext context = req.getServletContext();
//获取原始文件名
String oldName = fileImg.getOriginalFilename();
System.out.println(oldName);
System.out.println(context.getMimeType(oldName));
//判断上传文件是否为图片
if (!context.getMimeType(oldName).startsWith("image/")) {
return;
}
//获取存储路径
String realPath = context.getRealPath("/upload");
//创建新名字
String newName=UUID.randomUUID().toString()+"."+FilenameUtils.getExtension(oldName);
fileImg.transferTo(new File(realPath,newName));
//存储数据
img.setStorepath(realPath);
img.setStorename(newName);
service.addImg(img);
}
Images类
private Integer imgid;
private String storepath;
private String storename;
private String intro;
private Boolean isenabled;
private Date inputdate=new Date();
private MultipartFile fileImg;
API
MultipartFile :接收文件数据,命名必须和file标签name属性一致
getOriginalFilename:获取上传的文件名
transferTo:存储文件
2.2.文件下载
前端页面
<a href="${pageContext.request.contextPath }/download?filename=小师妹.jpg">文件下载</a>
代码实现
@RequestMapping(value = "/download", method = RequestMethod.GET)
public ResponseEntity<byte[]> download(HttpServletRequest request, @RequestParam("filename") String filename)
throws IOException {
String realPath = request.getServletContext().getRealPath("/upload");
File file = new File(realPath,filename);// 新建一个文件
//设置头信息
HttpHeaders headers = new HttpHeaders();
//设置响应的文件名
String downloadFileName = new String(filename.getBytes("UTF-8"), "iso-8859-1");
headers.setContentDispositionFormData("attachment", downloadFileName);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// MediaType:互联网媒介类型 contentType:具体请求中的媒体类型信息
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
}
7.Ajax检查用户名是否重复
<form>
<input type="text" id="txtUserName" name="txtUserName"><span id="spanInfo">...</span></input>
<input type="button" id="btnCheck" onclick="checkUserName();" value="检查用户名是否存在"></input>
</form>
7.2.js
function checkUserName(){
var xhr;
// 1 创建ajax对象
xhr = getAjax();
// 2 open
var userName = document.getElementById("txtUserName").value;
xhr.open("GET","/ajax1/isExsit?username=" + userName);
// 监听
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
var info = document.getElementById("spanInfo");
if(xhr.responseText == "true")
info.innerHTML="用户名已存在";
else
info.innerHTML="可以用此用户名";
}
}
// 3 send
xhr.send();
}
7.3.Servlet
@SuppressWarnings("serial")
@WebServlet("/isExsit")
public class UserNameCheckServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取参数
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
String userName = req.getParameter("username");
System.out.println(userName);
// 检查用户名是否存在
if("你好".equals(userName)){
resp.getWriter().print(true);
System.out.println("true");
} else {
resp.getWriter().print(false);
System.out.println("false");
}
}
}
8.Ajax post登录
Get 请求中文乱码:配置tomcat:URIEncoding="UTF-8"就可以解决
Post请求中文乱码:req.setCharacterEncoding("utf-8");