在shopback项目的WEB下新建登陆页面,利用ajax或者form表单进行登陆业务设计,
//三层 web service Dao
依旧是mvc模型,三层架构细分control层,
首先用户在jsp页面登陆,web层接收数据,调用其他层判断登陆是否成功,存放登陆标志,在利用分页技术获取初始页及页面长度等信息,然后然后多表查询获取商品详细信息放入list<Goods>,在goodsBean中增加相应查询的字段名作为成员变量,提供set、get方法。
之后在页面接收的list中,利用导入包jstl的c:foreach方法遍历展示list每一个goods元素,在其前后增加修改删除等超链接,调用相应函数传递当前goods的id,利用ajax进行后台web层增删查改,返回成功或失败信息封装进ResponseMessage中,利用json工具包,返回json对象到前台,前台再根据返回结果进行相应处理。
至于文件上传,及图像上传,可以在项目中编写上传下载servlet,也可自定义一个文件服务器,进行文件的上传下载,在服务器或上传类中,编写保存的位置,返回给请求端。下载类则根据请求地址,找到地址中的相应文件并写回。
同源策略
同源 : ip+port+… 相同
浏览器禁止js访问和当前页面不同源的服务器
浏览器禁止不同源的页面中的js获取对方的cookie
浏览器发送到服务器的请求会默认携带cookie信息,如果用户访问了恶意页面, 恶意页面中有ajax悄悄的访问用户
跨域(跨源)
有的时候, 我们自己的两个服务器之间需要相符访问, 这时, 就必须要跨域了, 比如说,图片服务器和本地服务器就属于不同源
要解决跨域问题, 就需要浏览器和服务器相互配合,浏览器发出跨域请求, 服务器允许跨域请求
两种请求
简单请求, 同时满足一下两个条件
请求方法是以下三种方法之一:
HEAD
GET
POST
HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
非简单请求: 不能同时满足以上两个条件
简单请求基本流程
浏览器如果发现是跨域请求, 就会在请求头中添加Origin字段,该字段的值为当前域名
服务器收到请求后,检查这个字段的值, 判断是否允许这个域名下的请求跨域进来
如果允许的话, 就需要在响应中返回特殊字段, 字段的值要设置为允许请求的域名
当浏览器接受到请求,检查服务返回的特殊字段,如果这个特殊字段中记录的值是符合当前域名, 才会将返回的数据传递给js的接收方法,否则就报错
Access-Control-Allow-Origin: http://localhost:8080
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
非简单请求基本流程
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight),就请求当前url指向的Servlet中的 OPTIONS方法
如果 OPTIONS 方法返回的信息中没有允许的特殊字段, 浏览器就会拒绝发起正式请求
除了Origin字段,"预检"请求的头信息包括两个特殊字段。
Access-Control-Request-Method
该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。
Access-Control-Request-Headers
该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
复选框分类查询
在goodsbean中加入typeIds[]成员变量
根据typeid数组内容查询,
并把传过去的goods类,在返回前端页面进行回显。判断已选择的typeid和所有typeId如果相同,则checked=cheked;
<form action="/shop/toMainPage" id="form">
<input id="search" name="name" value="${goods.name}"><button>搜索</button><br>
类型 :
<c:forEach items="${types}" var="item">
<%--form表单提交参数的时候,可以一个参数对应多个值--%>
${item.name}<input type="checkbox" name="typeIds" value="${item.id}" onclick="cc()"
<c:forEach items="${goods.typeIds}" var="typeId"> <c:if test="${typeId==item.id}">checked="checked"</c:if> </c:forEach> >
</c:forEach>
</form>
dao层 查询数据时,加入name like条件
public List getGoods(Goods goods){
Connection cn =null;
PreparedStatement ps =null;
ResultSet rs =null;
try {
cn = JDBCUtils.getConnection();
//拼接预制型sql语句
//sql语句中每拼接一个问号, 就需要往数组中存入一个对应的值,
//// 这样,我们就可以知道总共有几个问号,而且对应的值的顺序还是正确的
List objects =new ArrayList<>();
//基础sql语句
String sql ="select * from goods where status=1 ";
//如果有商品名称传递过来, 拼接到sql中
if(goods.getName()!=null){
sql +=" and name like ?";
objects.add("%"+goods.getName()+"%");
}
//如果有类型id传递过来,拼接到sql中,注意, 类型id可能时多个
if(goods.getTypeIds()!=null){
sql +=" and typeId in (" ;
int[] typeIds = goods.getTypeIds();//遍历类型id
for (int i =0; i < typeIds.length; i++) {
if(i==typeIds.length-1){
sql +="? )";
}else{
sql +="? , ";
}
}
objects.add(goods.getTypeIds());
}
ps = cn.prepareStatement(sql+" limit ? , ?");
//设置sql语句对应的参数值
int n =0;//记录已经设置了多少个参数值
for (Object object : objects) {
//如果拿到的值时一个数组, 需要转换并遍历
if(object.getClass().isArray()){
int[] typeIds = (int[]) object;
for (int i =0; i
n++;
ps.setObject(n,typeIds[i]);
}
}else{
n++;
ps.setObject(n,object);
}
}
ps.setInt(n+1,goods.getStart());
ps.setInt(n+2,goods.getPageSize());
rs = ps.executeQuery();
List list = DBUtils.selectMore(Goods.class,rs);
return list;
}catch (Exception e){
e.printStackTrace();
}finally {
JDBCUtils.close(rs,ps,cn);
}
return null;
}