Maven 项目启动,我们可以通过配置 Tomcat 插件来启动
org.apache.tomcat.maven
tomcat7-maven-plugin
2.1
8080
/travel
为了不每次启动项目都要去找这个命令,我们可以配置一下。后面我们启动直接点击启动的那个按钮即可
用户表,存储的和用户相关的信息
/**
* 用户实体类
*/
public class User implements Serializable {
private int uid;//用户id
private String username;//用户名,账号
private String password;//密码
private String name;//真实姓名
private String birthday;//出生日期
private String sex;//男或女
private String telephone;//手机号
private String email;//邮箱
private String status;//激活状态,Y代表激活,N代表未激活
private String code;//激活码(要求唯一)
//省略 get set toString 构造函数等方法
}
/**
* 分类实体类
*/
public class Category implements Serializable {
private int cid;//分类id
private String cname;//分类名称
//省略 get set toString 构造函数
}
tab_category 存储的就是上面导航栏里面的信息,这里我们是从数据库里面去取出来,而不是写死,返回的是 json 数据
[{"cid":8,"cname":"全球自由行"},{"cid":5,"cname":"国内游"},{"cid":4,"cname":"处境游"},{"cid":7,"cname":"抱团定制"},{"cid":6,"cname":"港澳游"},{"cid":2,"cname":"酒店"},{"cid":1,"cname":"门票"},{"cid":3,"cname":"香港车票"}]
//重数据库(tab_category)里面查询分类信息,填充到页面
$.get("category/findAll", {}, function (data) {
console.log(data);
//[{"cid":8,"cname":"全球自由行"},{"cid":5,"cname":"国内游"},{"cid":4,"cname":"处境游"},{"cid":7,"cname":"抱团定制"},{"cid":6,"cname":"港澳游"},{"cid":2,"cname":"酒店"},{"cid":1,"cname":"门票"},{"cid":3,"cname":"香港车票"}]
//收尾的两个 li 是固定的
var first = '首页 ';
var end = '收藏排行榜 ';
var lis = first;
//遍历 数组
for (var i = 0; i < data.length; i++) {
var li = '' + data[i].cname + ' ';
lis += li;
}
lis+=end;
//将lis字符串,设置到ul的html内容中
$("#category").html(lis);
})
tab_route 存储的就是点击不同的类别后,后面显示的数据信息
tab_category 和 tab_route 表是一对多的关系
通过tab_category表我们可以得到cid,然后通过cid我们就可以查询tab_route表里面的信息
前期分析很重要,我们先把后台代码写通了前台代码自然就简单多了
其实就是用户点击了不同类别的旅游景点信息后,就有一个cid,通过cid我们就可以去查询具体是那个类别的旅游信息,这个时候我们前头可以给服务器说我们需要哪些信息,服务器就返回什么样的信息
服务端:
- int totalCount //总记录数
- int totalPage //总页数
int currentPage //当前页码int pageSize //每页显示条数客户端:(发送ajax请求)
- currentPage //当前页码
- pageSize //每页显示条数
- cid //分页id
当前页码 每页显示条数,可以不通过服务器返回,应为这些信息是我们客服端发过去的,但是为了统一操作我们还是通过服务器返回,应为这些信息都是在一个json里面。当我们客服端不给这些信息的时候服务端还可以给默认的值
每次服务端返回的数据只有一页的数据量,但是还包含中的页码、种记录数 、每页显示条数。种页码种记录数是为了填写网页最下面的导航信息
每个旅游景点的详细信息我们封装在 Route 类里面
/**
* 旅游线路商品实体类
* 每一个项目的具体信息
*/
public class Route implements Serializable {
private int rid;//线路id,必输
private String rname;//线路名称,必输
private double price;//价格,必输
private String routeIntroduce;//线路介绍
private String rflag; //是否上架,必输,0代表没有上架,1代表是上架
private String rdate; //上架时间
private String isThemeTour;//是否主题旅游,必输,0代表不是,1代表是
private int count;//收藏数量
private int cid;//所属分类,必输
private String rimage;//缩略图
private int sid;//所属商家
private String sourceId;//抓取数据的来源id
private Category category;//所属分类
private Seller seller;//所属商家
private List routeImgList;//商品详情图片列表
//...
}
我们用另外一个类(PageBean)来封装所有的信息,不仅包含具体的景点信息还包含有多少个景点,多少页等记录
/**
* 分页对象
* 存储了各种页面信息
*/
public class PageBean {
private int totalCount;//总记录数
private int totalPage;//总页数
private int currentPage;//当前页码
private int pageSize;//每页显示的条数
private List list;//每页显示的数据集合
//...
}
在前台代码框里面有一个根据线路查询旅游景点的搜索框,我们需要完善这个搜索框
这里的查询和前面的根据cid查询不同类别的旅游线路数据 代码是一模一样的,我们只需要在原来的代码上修改一下即可,增加一个模糊查询,如果我们传给后台的代码中后 cname 我们就模糊查询,否则就是正常的查询即可
我们给搜索按钮绑定一个点击事件,然后获取输入的值,直接修改游览器的地址栏发送请求给 route_list.html 页面即可
//给搜索框绑定单击事件,获取搜索输入框的内容
$("#search-button").click(function () {
//线路名称
var rname = $("#search_input").val();
//alert(rname);
var cid = getParameter("cid")
//alert(cid);
//跳转路径 http://localhost:8080/travel_ssm/route_list.html?cid=5,拼接上 rname=xxx
location.href = "http://localhost:8080/travel_ssm/route_list.html?cid=" + cid + "&rname=" + rname;
})
我这里的查询,是通过MyBatis的动态SQL 写的,当然你也可以拼接字符串执行
/**
* 分页查询
* 如果有 rname 这个时候我们就需要模糊查询
*/
@RequestMapping("/pageQuery")
@ResponseBody
public PageBean pageQuery(HttpServletRequest request) throws UnsupportedEncodingException {
//1.接受参数
String currentPageStr = request.getParameter("currentPage");//当前页数
String pageSizeStr = request.getParameter("pageSize");//查询多少页
String cidStr = request.getParameter("cid");//
//接受rname 线路名称
String rname = request.getParameter("rname");//m
// System.out.println("rname:\t"+rname);
// rname = new String(rname.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); //rname 是中文,发送的还是get请求可能乱码 又有我配置了字符编码过滤器,这里是不可以使用的,不然正常的就会变成乱码
// System.out.println("rname:\t"+rname);
System.out.println("rname:\t"+rname);
System.out.println("rname 是不是为空:\t"+(rname == null));
if (rname == null || rname.equals("null")) {//没有给他一个空字符串
rname = null;
}
System.out.println("rname 是不是为空:\t"+(rname == null));
int cid = 0;//类别id
//2.处理参数
//在首页 搜索 cid = "null" 会发生类型转换异常
//http://localhost:8080/travel_ssm/route_list.html?cid=null&rname=西安
if (cidStr != null && cidStr.length() > 0 && !cidStr.equals("null")) {
cid = Integer.parseInt(cidStr);
}
int currentPage = 0;//当前页码,如果不传递,则默认为第一页
if (currentPageStr != null && currentPageStr.length() > 0) {
currentPage = Integer.parseInt(currentPageStr);
} else {
currentPage = 1;
}
int pageSize = 0;//每页显示条数,如果不传递,默认每页显示5条记录
if (pageSizeStr != null && pageSizeStr.length() > 0) {
pageSize = Integer.parseInt(pageSizeStr);
} else {
pageSize = 5;
}
//3. 调用service查询PageBean对象
//4. 将pageBean对象序列化为json,返回
return routeService.pageQuery(cid, currentPage, pageSize, rname);
}
分析:
我们抽象了一个 BaseServlet 类,让这个类继承HttpServlet,然后让其他类继承这个类
虽然我是使用的SpringMVC来做的,但是这个方法是一种很好的方法
程序中的 this 的指向是,谁调用就指向的就是谁,看下面的演示代码
父类:
public class Father{
public void service(){
System.out.println(this);
}
}
子类:
public class Son extends Father{
}
测试:
@Test
public void test() {
Son son = new Son();
son.service();
}
输出:
com.bug.service.impl.Son@3d012dd
通过上面的代码我们可以定义一个基础的类(BaseServlet ),让他去基础HttpServlet,其他类继承这个类,这个时候当程序调用 service 方法的时候我们就可以通过反射来执行响应的代码
BaseServlet
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//System.out.println("baseServlet的service方法被执行了...");
//完成方法分发
//1.获取请求路径
String uri = req.getRequestURI(); // /travel/user/add
System.out.println("请求uri:" + uri);// /travel/user/add
//2.获取方法名称
String methodName = uri.substring(uri.lastIndexOf('/') + 1);
System.out.println("方法名称:" + methodName);
//3.获取方法对象Method
//谁调用我?我代表谁
System.out.println(this);//UserServlet的对象cn.itcast.travel.web.servlet.UserServlet@4903d97e
try {
//获取方法
Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
//4.执行方法
//暴力反射
//method.setAccessible(true);
method.invoke(this, req, resp);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
解释:上面这个类由于子类没有重写父类的service方法,所有程序会首先执行父类的service方法,这个时候我们可以把请求参数提取出来,this.getClass() 的到的是子类对象,这个时候我们就通过反射的方式去执行子类相应的请求方法
这样做的好处是,当我们的请求参数是什么程序实际上就执行的是什么方法,应为我们子类没有重写父类的service方法,这个时候我们会执行父类的service方法,我们请求的参数是什么最后就会动态的执行子类的什么方法。
这个时候我们就可以把同一个操作放在同一类里面了,如果不这样做的话,下面的每个方法我们都需要写一个类来处理
@WebServlet("/user/*") // /user/add /user/find
public class UserServlet extends BaseServlet {
/**
* 注册功能
*/
public void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 省略业务代码
}
/**
* 查询单个对象
*/
public void findOne(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 省略业务代码
}
/**
* 退出功能
*/
public void exit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 省略业务代码
}
/**
* 激活功能
*/
public void active(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 省略业务代码
}
}
客户端传递一个 rid 然后重服务器的Session域中取出用户的 uid (没有的话我们uid置为-1反正不可能有这个人),然后在 tab_favorite 表中查询
/**
* 解决全站乱码问题,处理所有的请求
*/
@WebFilter("/*")
public class CharchaterFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse rep, FilterChain filterChain) throws IOException, ServletException {
//将父接口转为子接口
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) rep;
//获取请求方法
String method = request.getMethod();
//解决post请求中文数据乱码问题
if(method.equalsIgnoreCase("post")){
request.setCharacterEncoding("utf-8");
}
//处理响应乱码
response.setContentType("text/html;charset=utf-8");
filterChain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
我是使用的SpringMVC 这个时候我只需要在 web.xml 里面配置过滤器即可
CharacterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
forceRequestEncoding
true
forceResponseEncoding
true
CharacterEncodingFilter
/*