wisdomsell-day2(智能商贸系统第二天)

北慕城南 提交于 2019-12-14 06:20:58

wisdomsell-day2(智能商贸系统第二天)

1.抽取repository的父接口

/**
因为扫描包扫描的是repository下面的所有,如果不打上该注释,就会实现它
父接口不能确定类型
@NoRepositoryBean告诉spring不要去实现它
*/
@NoRepositoryBean
public interface BaseRepository<T,ID extends Serializable> extends JpaRepository<T,ID>,JpaSpecificationExecutor<T> {
}

同时子类也需要改为继承该接口

public interface EmployeeRepository extends BaseRepository<Employee,Long>

2.创建service层

2.1创建父接口

这里除了常规的CRUD以外,另外多写了3个方法

创建好后,再创建子接口去继承

public interface IBaseService<T,ID extends Serializable> {
    void save(T t);
    void delete(ID id);
    T findOne(ID id);
    List<T> findAll();
    //扩展操作
    //1.根据查询对象进行查询
    List<T> queryAll(BaseQuery query);
    //2.根据查询对象拿到分页数据
    Page<T> queryPage(BaseQuery query);
    //3.根据JPQL进行查询
    /**
     * 主要是为了去解决你必须手动写jpql来查询的东西
     * params 参数
     * 这里属性和值都是不确定的
     */
    List<Object> queryByJpql(String jpql,Object... params);
}

2.2创建父接口的实现类

注意事项:1:一般情况来说,因为查询是不需要事物的,而且查询的时候多点,所以可以在类上打上注解,但是不一定绝对,需要根据实际情况来定2:因为这个实现类注入的是接口,但是父类接口是没有被spring实现的,这就是为什么加入泛型的原因3:以后可能出现需要用到写jpql的情况

创建好父类实现后,再创建一个子类实现类,并继承父类

@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public  class BaseServiceImpl<T,ID extends Serializable> implements IBaseService<T,ID> {
    /**
     * 这个父接口本身没有实现
     * 所以注入的其实是他的所有子接口实现(),所以spring不知道是哪个接口
     * 所以为了让spring知道,在后面加入泛型
     * 父接口的实现,这个类就是一个父类,根本就不用它创建对象,所以最好把该类变为抽象类,免得去创建对象
     * 至于最后如何确定类型,则由最后的子类来确定
     * 这里你写abstract只是断念想,你不写也是可以的
     */
    @Autowired
    private BaseRepository<T,ID> baseRepository;
    //保证事物都是同一个线程中的
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    @Transactional
    public void save(T t) {
        baseRepository.save(t);
    }



    @Override
    @Transactional
    public void delete(ID id) {
        baseRepository.delete(id);
    }

    @Override
    public T findOne(ID id) {
        return baseRepository.findOne(id);
    }

    @Override
    public List<T> findAll() {
        return baseRepository.findAll();
    }
    //根据查询对象进行查询
    @Override
    public List<T> queryAll(BaseQuery query) {
        //拿到查询规则
        Specification spec = query.creatSpec();
        //进行查询
        return baseRepository.findAll(spec);
    }
    //根据查询对象拿到分页数据
    @Override
    public Page<T> queryPage(BaseQuery query) {
        //1.拿到排序对象
        Sort sort = query.createSort();
        //2.拿到分页对象
        Pageable pageable = new PageRequest(query.getJpaCurrentPage(),query.getPageSize(),sort);
        //3.拿到查询规则
        Specification spec = query.creatSpec();
        //4.进行查询
        return baseRepository.findAll(spec,pageable);
    }
    //根据JPQL进行查询
    @Override
    public List<Object> queryByJpql(String jpql, Object... params) {
        //1.创建query对象
        Query query = entityManager.createQuery(jpql);
        //2.循环params参数,设置值从1开始
        for (int i=0;i<params.length;i++){
            query.setParameter(i+1,params[i]);
        }
        //返回数据
        return query.getResultList();
    }
}

3.测试service

点击注解进入就可以发现该注解是否有元注解

//@Inherited 只要有这个元注解,表示该注解是可以被继承的
public class test extends EmployeeRepositoryTest {
    @Autowired
    private IEmployeeService iEmployeeService;

     @Test
      public void testFindAll()throws Exception{
         List<Employee> list = iEmployeeService.findAll();
         list.forEach(e-> System.out.println(e));
     }
     //根据用户名来进行查询
     @Test
      public void testQueryAll()throws Exception{
         EmployeeQuery employeeQuery = new EmployeeQuery();
         employeeQuery.setUsername("1");

         System.out.println(iEmployeeService.queryAll(employeeQuery));
      }
    //根据查询对象拿到分页数据
     @Test
      public void testQueryPage()throws Exception{
         EmployeeQuery employeeQuery = new EmployeeQuery();
         employeeQuery.setUsername("admin");
         employeeQuery.setCurrentPage(1);
         employeeQuery.setPageSize(10);
         System.out.println(iEmployeeService.queryPage(employeeQuery));
      }
}

4.准备Spring-MVC

第一天没用的上传解析器在这里就可以用了,注意名字只能为multipartResolver

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation=
               "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
        <!--1.扫描包-->
        <context:component-scan base-package="com.yyk.aisell.controller"></context:component-scan>
        <!--2.SpringMVC注解支持-->
        <mvc:annotation-driven/>
        <!--3.静态资源放行-->
        <mvc:default-servlet-handler/>
        <!--4.视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/views/"></property>
            <property name="suffix" value=".jsp"></property>
        </bean>
        <!--5.上传解析  暂时不用-->
    <!--5.上传解析器 CommonsMultipartResolver-->
    <!-- 注意:上传解析器的id必需:multipartResolver -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize">
            <value>10485760</value>
        </property>
    </bean>

5.准备web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         id="WebApp_ID" version="3.1">

  <!--这里必须xml里面要用高版本的,至少都要2.4版本-->
  <!--先配置一个监听器-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <!--读取spring配置文件-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>



  <!--核心控制器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--读取springMVC的配置文件-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:applicationContext-mvc.xml</param-value>
    </init-param>
    <!--核心控制器在启动tomcat的时候就自动创建-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!--编码过滤器-->
  <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

6.controller层以及分页BUG

我们在下面代码分页跳转的时候,发现页面无法显示内容,查看F12后发现是后台穿回去的数据和前端需要的不一样所导致的,在这里可以有两种办法,一种,用map的形式将所需要的key和value值传入,另外一种则是新建一个类

@Controller
@RequestMapping("/employee")
public class EmployeeController extends BaseController {
    @Autowired
    private IEmployeeService employeeService;

    @RequestMapping("/index")
    public String index(){
        return "employee/index";
    }

    /**
     * 此时你访问page,发现页面没有显示数据,原因是后台的头和前端的头不一样
     *  前端显示是 rows total
     *
        后台传过去的是         content
                                 0
                                 id	1
                                 username	"admin"
                                 password	"48d05cc43f3bfe2510394e8dfcef919a"
                                 email	"admin@itsource.com"
                                 age	34
     所以解决的办法有两个:一个是创建map集合,另外一个就是创建一个类,将字段传进去,这里选择后一种方法
     */
    @RequestMapping("/page")
    @ResponseBody
    public EasyUiPage list(EmployeeQuery employeeQuery){
        Page<Employee> page = employeeService.queryPage(employeeQuery);
        EasyUiPage easyUiPage = new EasyUiPage(page);
        return  easyUiPage;
    }

    @RequestMapping("/list")
    @ResponseBody
    public List<Employee> findAll(){
        return employeeService.findAll();
    }

    //删除数据
    @RequestMapping("/delete")
    @ResponseBody
    public JsonResult delete(Long id){
        try {
            employeeService.delete(id);
            return new JsonResult();
        }catch (Exception e){
            return new JsonResult(false,e.getMessage());
        }
    }
}

6.1创建EasyUIPage

这个就是独属于前台的

public class EasyUiPage<T> {
    private Long total;
    private List<T> rows = new ArrayList<>();
    //在这里直接将后台的page参数传进去,变为前台需要的参数
    public EasyUiPage(Page page) {
        this.total = page.getTotalElements();
        this.rows = page.getContent();
    }

    @Override
    public String toString() {
        return "EasyUiPage{" +
                "total=" + total +
                ", rows=" + rows +
                '}';
    }

    public Long getTotal() {
        return total;
    }

    public void setTotal(Long total) {
        this.total = total;
    }

    public List<T> getRows() {
        return rows;
    }

    public void setRows(List<T> rows) {
        this.rows = rows;
    }
}

6.2实现分页

发送请求过去,并且带了参数,只是这两个值在第一天的BaseQuery类中没有,所以在类中加入两个set方法即可,因为传参,是调用的set方法

 //为了兼容easyui提供的方法,因为后台给的是rows和page
    public void setPage(int page){
        this.currentPage=page;
    }
    public void setRows(int rows){
        this.pageSize=rows;
    }

7.高级查询功能实现

7.1准备工具栏

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <%--jsp如果有相同的头部,直接提取出去,在这里进行引入--%>
    <%@include file="/WEB-INF/views/head.jsp"%>
    <%--引入当前模块对应的js--%>
    <script src="/js/model/employee.js">

    </script>
</head>
<body>

<div id="toolbar" style="padding:5px;height:auto">
    <div style="margin-bottom:5px">
        <a href="#" data-method="add" class="easyui-linkbutton" iconCls="icon-add" plain="true">添加</a>
        <a href="#" data-method="update" class="easyui-linkbutton" iconCls="icon-edit" plain="true">修改</a>
        <a href="#" data-method="delete" class="easyui-linkbutton" iconCls="icon-remove" plain="true">删除</a>
    </div>
    <form id="searchForm" method="post">
        用户名: <input name="username" class="easyui-textbox" style="width:80px">
        邮件: <input name="email" class="easyui-textbox" style="width:80px">
        <a href="#"  data-method="search"  class="easyui-linkbutton" iconCls="icon-search">查询</a>
    </form>
</div>

<%--fit自适应,有了以后width和height就失去作用了--%>
<table id="datagrid" class="easyui-datagrid"
       data-options="url:'/employee/page',fitColumns:true,singleSelect:true,fit:true,toolbar:'#toolbar',pagination:true">
    <thead>
    <tr>
        <th data-options="field:'id',width:100">编码</th>
        <th data-options="field:'username',width:100">名称</th>
        <th data-options="field:'age',width:100,align:'right'">年龄</th>
        <th data-options="field:'password',width:100">密码</th>
        <th data-options="field:'email',width:100">邮件</th>
    </tr>
    </thead>
</table>
</body>
</html>

7.2将js的引用头提取出来

这里引入了一个Jquery的扩展包,能够方便处理数组和json的转换,因为easyUi没有实现这个功能

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--引入easyUI样式--%>
<link rel="stylesheet" type="text/css" href="/easyui/themes/default/easyui.css">
<%--引入图标--%>
<link rel="stylesheet" type="text/css" href="/easyui/themes/icon.css">
<%--引入jquery--%>
<script type="text/javascript" src="/easyui/jquery.min.js"></script>
<%--jQuery的扩展包 --%>
<script type="text/javascript" src="/easyui/plugin/jquery.jdirk.js"></script>
<%--easyUI核心文件--%>
<script type="text/javascript" src="/easyui/jquery.easyui.min.js"></script>
<%--引入一个国际化--%>
<script type="text/javascript" src="/easyui/locale/easyui-lang-zh_CN.js"></script>

7.3将不同的属性的js代码单独写

不同类型对应不同的js代码,单独创建js来放置

$(function () {

    //常用的元素都先在这里获取到
    var datagrid = $("#datagrid");
    var searchForm = $("#searchForm")

    //事件
    $("*[data-method]").on("click",function () {
        //1.拿到当前对应的方法名
        var methodName = $(this).data("method");
        //2.调用方法
        itsource[methodName]();
    })

    itsource ={
        add(){
            alert("add");
        },
        update(){alert("update");},
        delete(){
            //1.获取选中的行
            var row = datagrid.datagrid("getSelected");
            //2.如果这一行不存在(给出提示,后台代码不再执行)
            if(!row){
                $.messager.alert('提示','请选中一行再来删除,好嘛!',"warning");
                return;
            }
            //3.让用户确定是否删除
            $.messager.confirm('确认','您确认想要删除记录吗?',function(r){
                if (r){
                    //4.通过Ajax请求进行删除
                    // 参数一:请求路径   参数二:请求参数   参数三:回调
                    // result:是后端返回的结果
                    $.get("/employee/delete",{id:row.id},function (result) {
                        if(result.success){
                            //5.刷新页面
                            datagrid.datagrid("reload");
                        }else{
                            //给出错误提示
                            $.messager.alert('提示',`删除失败,原因是:${result.msg}`,"error");
                        }
                    })
                }
            });

        },
        //高级查询功能
        search(){
            //1.拿到查询的值
            var params = searchForm.serializeObject();
            //2.进行查询
            datagrid.datagrid("load",params);
        }
    };


})

8.删除功能实现

删除的思想:当我们点击删除时,如果没有点击任意一行,就提示:请点击一行,如果点击到任意一行,就提示是否进行删除,如果删除失败,则返回一个消息,删除成功就重新加载该页面,可以先考虑从后台代码写

8.1删除后台

public class JsonResult {
    //默认删除是成功的
    private boolean success = true;
    //如果失败,就回返回消息
    private String msg ;

    //如果构造方法里面有参数就是删除失败,没有参数则成功

    public JsonResult(boolean success,String msg){
        this.success = success;
        this.msg = msg;
    }

    public JsonResult() {
    }

    public boolean getSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

8.2控制层

 //删除数据
    @RequestMapping("/delete")
    @ResponseBody
    public JsonResult delete(Long id){
        try {
            employeeService.delete(id);
            return new JsonResult();
        }catch (Exception e){
            return new JsonResult(false,e.getMessage());
        }
    }
}

8.3前台

 delete(){
            //1.获取选中的行
            var row = datagrid.datagrid("getSelected");
            //2.如果这一行不存在(给出提示,后台代码不再执行)
            if(!row){
                $.messager.alert('提示','请选中一行再来删除,好嘛!',"warning");
                return;
            }
            //3.让用户确定是否删除
            $.messager.confirm('确认','您确认想要删除记录吗?',function(r){
                if (r){
                    //4.通过Ajax请求进行删除
                    // 参数一:请求路径   参数二:请求参数   参数三:回调
                    // result:是后端返回的结果
                    $.get("/employee/delete",{id:row.id},function (result) {
                        if(result.success){
                            //5.刷新页面
                            datagrid.datagrid("reload");
                        }else{
                            //给出错误提示
                            $.messager.alert('提示',`删除失败,原因是:${result.msg}`,"error");
                        }
                    })
                }
            });

        },
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!