销售宝系统_Day02(框架搭建)

本文详细介绍了如何使用SpringDataJpa扩展功能,实现与EasyUI前端框架的数据兼容,涵盖自定义Repository、Service层抽象、SpringMVC集成及高级查询条件的实现。
  • 准备Service层
  • 集成SpringMVC(Controller层)
  • 添加EasyUI展示主页面
  • 完成一个数据的查询功能

一、Spring Data Jpa扩展

  1. 首先在repository包下面创建一个名为BaseRepository的接口
package com.xpc.repository;

import com.xpc.query.BaseQuery;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;

import java.io.Serializable;
import java.util.List;

/**
 1. 自定义一个Repository,它是JpaRepository的功能基础上继承增强
 2. 在上面添加@NoRepositoryBean标注,这样Spring Data Jpa在启动时就不会去实例化BaseRepository这个接口
 3. @param <T>
 4. @param <ID>
 */
@NoRepositoryBean
public interface BaseRepository<T,ID extends Serializable> extends JpaRepository<T,ID>,JpaSpecificationExecutor<T> {
    //根据Query拿到分页对象(分页)
    Page findPageByQuery(BaseQuery baseQuery);

    //根据Query拿到对应的所有数据(不分页)
    List<T> findByQuery(BaseQuery baseQuery);

    //根据jpql与对应的参数拿到数据
    List findByJpql(String jpql,Object... values);
}
  1. 在同包下创建一个类BaseRepositoryImpl来实现BaseRepository
package com.xpc.repository;

import com.xpc.query.BaseQuery;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.io.Serializable;
import java.util.List;

/**
 1. 实现父类中的三个方法
 2. @param <T>
 3. @param <ID>
 */
public class BaseRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID> implements BaseRepository<T,ID> {

    private final EntityManager entityManager;

    //必需要实现父类的这个构造器
    public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
        super(domainClass, em);
        this.entityManager = em;
    }

    @Override
    public Page findPageByQuery(BaseQuery baseQuery) {
        //第一步:拿到所有高级查询条件
        Specification spec = baseQuery.createSpec();
        //第二步:拿到排序的值
        Sort sort = baseQuery.createSort();
        //第三步:根据条件查询分页数据并且返回
        Pageable pageable = new PageRequest(baseQuery.getJpaCurrentPage(), baseQuery.getPageSize(),sort);
        Page<T> page = super.findAll(spec, pageable);
        return page;
    }

    @Override
    public List<T> findByQuery(BaseQuery baseQuery) {
        //第一步:拿到所有高级查询条件
        Specification spec = baseQuery.createSpec();
        //第二步:拿到排序的值
        Sort sort = baseQuery.createSort();
        //第三步:拿到数据返回
        return findAll(spec, sort);
    }

    @Override
    public List findByJpql(String jpql, Object... values) {
        //第一步:创建Query对象
        Query query = entityManager.createQuery(jpql);
        //第二步:把值设置到Query对象中去
        if (values!=null) {
            for (int i = 0; i < values.length; i++) {
                query.setParameter(i + 1, values[i]);
            }
        }
        //第三步:返回数据
        return query.getResultList();
    }
}
  1. 再创建一个类BaseRepositoryFactoryBean
package com.xpc.repository;

import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

import javax.persistence.EntityManager;
import java.io.Serializable;

public class BaseRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T,S,ID> {

    @Override
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
        return new MyRepositoryFactory<T,ID>(entityManager); //注:这里创建是我们的自定义类
    }

    //继承JpaRepositoryFactory后,把返回的对象修改成我们自己的实现
    private static  class MyRepositoryFactory<T,ID extends Serializable>   extends JpaRepositoryFactory{
        private final EntityManager entityManager;
        /**
         * Creates a new {@link JpaRepositoryFactory}.
         *
         * @param entityManager must not be {@literal null}
         */
        public MyRepositoryFactory(EntityManager entityManager) {
            super(entityManager);
            this.entityManager = entityManager;
        }
        //这里返回最后的功能对象
        @Override
        protected Object getTargetRepository(RepositoryInformation information) {
            return new BaseRepositoryImpl<T,ID>((Class<T>)information.getDomainType(),entityManager);
        }
        //确定功能对象的类型
        @Override
        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return BaseRepositoryImpl.class;
        }
    }
}
  1. 修改applicationContext.xml 中配置
    <!-- 配置SpringDataJpa -> 让咱们的某一层的代码支持SpringDataJpa
            只要发现咱们的接口继承了JpaRepository,它就会自动去完成相应的CRUD-->
            
    <jpa:repositories base-package="com.xpc.repository"
                      entity-manager-factory-ref="entityManagerFactory"
                      transaction-manager-ref="transactionManager"
                      <!--加上下面这句-->
                      factory-class="com.xpc.repository.BaseRepositoryFactoryBean"/>
  1. 最后就是EmployeeRepository来继承BaseRepository这个接口
public interface EmployeeRepository extends BaseRepository<Employee,Long>{
		//后面所有的实体类对应的Repository接口都有来继承BaseRepository
}

完成之后可以在test里面测试一下,是否能实现公共

二、完成Service层

  1. 创建service层所有接口的父类IBaseService
package com.xpc.service;

import com.xpc.query.BaseQuery;
import org.springframework.data.domain.Page;

import java.io.Serializable;
import java.util.List;

public interface IBaseService<T,ID extends Serializable> {
    //添加与修改数据      JPA会自动的区分是修改还是添加
    void save(T t);

    //根据id删除一条数据
    void delete(ID id);

    //根据id查询到一条数据
    T findOne(ID id);

    //查询所有数据
    List<T> findAll();

    //根据Query拿到分页对象(分页)
    Page findPageByQuery(BaseQuery baseQuery);

    //根据Query拿到对应的所有数据(不分页)
    List<T> findByQuery(BaseQuery baseQuery);

    //根据jpql与对应的参数拿到数据
    List findByJpql(String jpql,Object... values);
}
  1. 创建BaseServiceImpl
package com.xpc.service.impl;

import com.xpc.query.BaseQuery;
import com.xpc.repository.BaseRepository;
import com.xpc.service.IBaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;
//事务支持,默认不开启事务,在需要事务的方法上面加@Transactional这个注解
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class BaseServiceImpl<T,ID  extends Serializable> implements IBaseService<T,ID> {

    //这个地方必须要加上泛型才能确认类型
    @Autowired
    private BaseRepository<T, ID> baseRepository;

    @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 Page findPageByQuery(BaseQuery baseQuery) {
        return baseRepository.findPageByQuery(baseQuery);
    }

    @Override
    public List<T> findByQuery(BaseQuery baseQuery) {
        return baseRepository.findByQuery(baseQuery);
    }

    @Override
    public List findByJpql(String jpql, Object... values) {
        return baseRepository.findByJpql(jpql, values);
    }
}
  1. 创建IEmployeeService
package com.xpc.service;

import com.xpc.domain.Employee;

public interface IEmployeeService extends IBaseService<Employee,Long> {
}
  1. 创建EmployeeServiceImpl
package com.xpc.service.impl;

import com.xpc.domain.Employee;
import com.xpc.service.IEmployeeService;
import org.springframework.stereotype.Service;

@Service
public class EmployeeServiceImpl extends BaseServiceImpl<Employee,Long> implements IEmployeeService {
}
  1. 完成之后在test里面测试
package com.xpc.service;

import com.xpc.BaseTest;
import com.xpc.domain.Employee;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

public class EmployeeTset extends BaseTest {
    @Autowired
    private IEmployeeService iEmployeeService;
    @Test
    public void  test01(){
        List<Employee> list = iEmployeeService.findAll();
        list.forEach(e-> System.out.println(e));
    }
}

三、集成SpringMVC

  1. 配置applicationContext-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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
">
    <!--配置SpringMVC,有5大组件必需加上-->
    <!--扫描Controller-->
    <context:component-scan base-package="com.xpc.web.controller" />
    <!--支持SpringMVC的注解-->
    <mvc:annotation-driven />
    <!--静态资源放行-->
    <mvc:default-servlet-handler />
    <!--视图解析器(加后缀与后缀) InternalResourceViewResolver-->
    <bean  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <!-- 错误:提示告诉开发者你没有配置文件上传解析器。 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 设置上传文件的最大尺寸为1MB -->
        <property name="maxUploadSize">
            <value>1048576</value>
        </property>
    </bean>

    <!-- Spring MVC 配置 -->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>application/json; charset=UTF-8</value>
                        <value>application/x-www-form-urlencoded; charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
</beans>
  1. 配置web.xml
    要自己改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">

    <!--配置Spring的核心文件的位置-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!--启动Spring
    Spring这个监听器会去找一个默认的配置文件: [/WEB-INF/applicationContext.xml]-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>


    <!--配置控制器Servlet是访问到的时候才创建,我们希望它随着tomcat(服务器)启动就创建
        启动时会去找Springmvc的核心配置文件 -> 默认:/WEB-INF/dispatcherServlet-servlet.xml-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext-mvc.xml</param-value>
        </init-param>
        <!--load-on-startup:随着服务器启动而加载-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <!--杠:符合咱们RESTful风格的软件
              SpringMVC说的RESTful风格,这个会导致访问不到静态资源-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--SpringMVC中POST请求的乱码问题-->
    <!-- 配置编码方式过滤器,注意一点:要配置在所有过滤器的前面 -->
    <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>
  1. 创建Controller与页面
    ① 创建controller层的父类BaseController
package com.xpc.web.controller;

//controller层的父类    目前还没用,为以后做准备
public class BaseController {
}

② 创建EmployeeController

package com.xpc.web.controller;

import com.xpc.common.UiPage;
import com.xpc.query.EmployeeQuery;
import com.xpc.service.IEmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

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

    @RequestMapping("/index")
    public String index() {
        //根据配置,这里会跳到/WEB-INF/views/employee/employee.jsp页面
        return "employee/employee";
    }

    @RequestMapping("/list")
    @ResponseBody
    public List<Employee> list(){
        return employeeService.findAll();
    }
}
  1. 在webapp/WEB-INF/views/employee下面创建一个employee.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>访问成功</h1>
</body>
</html>

然后就可以启动Tomcat进行测试看是否成功了
http://localhost/employee/employee

四、引入主页面

  1. 首先把easyui文件拷贝到webapp下面

  2. 在controller层创建一个MainController类,当主页的入口

package com.xpc.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

//访问主页的一个controller
@Controller
public class MainController {
    @RequestMapping("/main")
    public String index() {
        return "forward:WEB-INF/views/main.jsp";
    }
}
  1. 在webapp/WEB-INF/views下面创建head.jsp
    它当作公共的样式引入jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<!-- easyui的样式支持 -->
<link rel="stylesheet" type="text/css" href="/easyui/themes/default/easyui.css">

<!-- easyui中的图标样式支持 -->
<link rel="stylesheet" type="text/css" href="/easyui/themes/icon.css">

<!-- 颜色:class="c1 ~ c8" -->
<link rel="stylesheet" type="text/css" href="/easyui/themes/color.css">

<!-- jquery的支持(easyui是基于jQuery的,所以必需要先引入jQuery) -->
<script type="text/javascript" src="/easyui/jquery.min.js"></script>

<!-- jquery的加强(jquery加强是基于jQuery的,所以必需要先引入jQuery) -->
<script type="text/javascript" src="/easyui/plugin/jquery.jdirk.js"></script>

<!-- easyui的核心js支持 -->
<script type="text/javascript" src="/easyui/jquery.easyui.min.js"></script>

<!-- easyui的国际化支持(当然是选中文) -->
<script type="text/javascript" src="/easyui/locale/easyui-lang-zh_CN.js"></script>
  1. 准备静态菜单数据(先准备点假数据看效果,后面换成数据库查询到的)
    webapp/json下面创建一个menu.json
[{
  "id":1,
  "text":"基本数据",
  "iconCls":"icon-save",
  "children":[{
    "text":"用户管理",
    "url":"/employee/index"
  },{
    "text":"部门管理",
    "url":"/employee/index"
  }]
}]
  1. 在webapp/WEB-INF/views创建一个main.jsp
    里面的都是用的easyui的框架,http://www.jeasyui.net/tutorial/ 这是easyui中文网
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>销售王首页</title>
    <%@include file="/WEB-INF/views/head.jsp" %>  <%--引入样式--%>
</head>
<body>
        <div id="cc" class="easyui-layout" data-options="fit:true">
            <div data-options="region:'north',split:true" style="height:100px;text-align: center;">
                <h1>欢迎来到智能商贸系统</h1>
            </div>
            <div data-options="region:'west',title:'信息菜单',split:true" style="width:200px;">
                <ul id="tree_data"></ul>
            </div>
            <div id="tabs1" data-options="region:'center'" class="easyui-tabs" style="background:#eee;">
                <div title="首页" style="text-align: center;padding-top:100px;font-size: 40px">
                    欢迎使用源码时代智销系统<br/><br/>第V.0版本
                </div>
            </div>
        </div>
        <script>
            $(function() {
                $("#tree_data").tree({
                    url: "/json/menu.json",
                    method: 'get',
                    onClick: function(data) {
                        var url = data.url;
                        if(url) { //如果该节点存在url,再获取文本和图标
                            var text = data.text;
                            var icon = data.iconCls;//
                            if($('#tabs1').tabs('exists',text)){//判断选项卡中是否存在相应text的选项卡
                                $('#tabs1').tabs('select',text);//选中指定text的选项卡
                            }else{
                                //添加
                                $('#tabs1').tabs('add', {
                                    title: text,
                                    iconCls: icon,
                                    content: '<iframe src="'+url+'" height="100%" width="100%" frameborder="0" scrolling="auto"></iframe>',
                                    closable: true
                                });
                            }
                        }
                    }
                });
            });
        </script>
    </body>
</html>

就这样,主页就搭建成功了,可以 开启Tomcat测试了 http://localhost/main

五、员工的查询页面

  1. 在employee.jsp里面加一个table
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>员工</title>
    <%--引入相应的css与js--%>
    <%@include file="/WEB-INF/views/head.jsp" %>
</head>
<body>
<%-- pagination:分页条支持 --%>
<table id="employeeGrid" class="easyui-datagrid"
       data-options="url:'/employee/page',fitColumns:true,singleSelect:true,
                fit:true,pagination:true,toolbar:'#gridTools'">
    <thead>
    <tr>
        <th data-options="field:'id',width:100">编码</th>
        <th data-options="field:'username',width:100">名称</th>
        <th data-options="field:'password',width:100">密码</th>
        <th data-options="field:'email',width:100">邮件</th>
        <th data-options="field:'age',width:100">年龄</th>
    </tr>
    </thead>
</table>
</body>
</html>
  1. 新建一个UiPage类
    由于咱们SpringDataJpa返回的数据和EasyUI中的数据匹配不上,所以咱们准备一个类,直接把SpringDataJpa的Page对象进行一次封装,返回给前台即可:
package com.xpc.common;

import org.springframework.data.domain.Page;
import java.util.List;

public class UiPage {
			//前台接收只需要total和rows这两个参数
    private long total; //总条数
    private List rows; //每页数据
    public UiPage(){}
    public UiPage(Page page){
        total = page.getTotalElements();
        rows = page.getContent();
    }

    public long getTotal() {
        return total;
    }

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

    public List getRows() {
        return rows;
    }

    public void setRows(List rows) {
        this.rows = rows;
    }
}
  1. BaseQuery添加方法
    前台传过来的当前页叫:page,每条条数叫:rows,和我们类中的字段对应不上所以需要添加两个方法来接收前台传来的参数
    //兼容Easyui的分页
    public void setPage(int page) {
        this.currentPage = page;
    }
    public void setRows(int rows) {
        this.pageSize = rows;
    }
  1. 修改EmployeeController的数据返回类型
package com.xpc.web.controller;

import com.xpc.common.UiPage;
import com.xpc.query.EmployeeQuery;
import com.xpc.service.IEmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

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

    @RequestMapping("/index")
    public String index() {
        //根据配置,这里会跳到/WEB-INF/views/employee/employee.jsp页面
        return "employee/employee";
    }

    @RequestMapping("/page")
    @ResponseBody
    public UiPage page(EmployeeQuery query){
        Page page = employeeService.findPageByQuery(query);
        UiPage uiPage =  new UiPage(page);
        return uiPage;
    }
/*
    @RequestMapping("/list")
    @ResponseBody
    public List<Employee> list(){
        return employeeService.findAll();
    }
*/
}

这样员工的查询和分页就 完成了,打开TomCat测试吧 http://localhost/employee/index

六、完善Employee对象

  1. 加入部门模块(只做到service部分)
    就是在domain层创建一个Department类,其他层的写法和Employee类一样,复制粘贴,改一下就好了
    在这里插入图片描述
  2. 往Employee里面加入头像和部门两个字段
    //头像
    private String headImage;
    //部门
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="department_id")
    //@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})  //加这个注解是为了解决JPA和Spring框架的集成问题
    private Department department;
    
       get/set方法省略
  1. employee.jsp也要加上头像和部门这两个列
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>员工</title>
    <%--引入相应的css与js--%>
    <%@include file="/WEB-INF/views/head.jsp" %>
    <script src="/js/model/employee.js"></script>
</head>
<body>

<%-- pagination:分页条支持 --%>
<table id="employeeGrid" class="easyui-datagrid"
       data-options="url:'/employee/page',fitColumns:true,singleSelect:true,
                fit:true,pagination:true,toolbar:'#gridTools'">
    <thead>
    <tr>
        <th data-options="field:'id',width:100">编码</th>
                <%--formatter:formatImage这是在调用employee.js里名为formatImage的函数--%>
        <th data-options="field:'headImage',width:100,formatter:formatImage">头像</th>
        <th data-options="field:'username',width:100">名称</th>
        <th data-options="field:'password',width:100">密码</th>
        <th data-options="field:'email',width:100">邮件</th>
        <th data-options="field:'age',width:100">年龄</th>
        <th data-options="field:'department',width:100,formatter:formatDept">部门</th>
    </tr>
    </thead>
</table>
  1. 在webapp/js/model下面添加一个employee.js文件
    里面写头像和部门的js代码
function formatImage(value,row,index) {
    return `<img src="${value}" width="50" height="50">`;
}

function formatDept(value) {
    return value?value.name:"";
}
  1. no Session问题解决

    运行时我们会发现没有数据,然后通过js调试工作可以看到,返回报错 no-session
    我们在web.xml加上以下代码即可

    <!-- 配置过滤器: 我想让EntityManager对象在我的jsp页面显示完毕后再关闭-->
    <filter>
        <filter-name>openEM</filter-name>
        <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>openEM</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  1. No serializer问题解决

方法一、在类上加属性:生成的时候把这个字段忽略了:
(不推荐使用,懒加载越多,这个注解加的就越多)

@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})

方法二、新建一个类,改mvc.xml指向的位置

① 新建一个名为CustomMapper的类

package com.xpc.common;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
//No serializer问题结局而加的类
public class CustomMapper extends ObjectMapper {
    public CustomMapper() {
        this.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 设置 SerializationFeature.FAIL_ON_EMPTY_BEANS 为 false
        this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    }
}

② 在applicationContext-mvc.xml中配置一下即可

    <!-- Spring MVC 配置 -->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>application/json; charset=UTF-8</value>
                        <value>application/x-www-form-urlencoded; charset=UTF-8</value>
                    </list>
                </property>
                
                
                <!-- No serializer:配置 objectMapper 为我们自定义扩展后的 CustomMapper,解决了返回对象有关系对象的报错问题 -->
                <property name="objectMapper">
                    <bean class="com.xpc.common.CustomMapper"></bean>
                </property>


            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

七、加入高级查询条件

  1. 添加一个公共类UtilController,用来查询展示我们的下拉数据
package com.xpc.web.controller;

import com.xpc.domain.Department;
import com.xpc.service.IDepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

/**
 * 工具类:返回所有的下拉数据
 */
@Controller
@RequestMapping("/util")
public class UtilController {

    @Autowired
    private IDepartmentService departmentService;

    @RequestMapping("/depts")
    @ResponseBody
    public List<Department> findAllDepts(){
             //返回部门的所有数据
        return departmentService.findAll();
    }
}

  1. employee.jsp 加入功能条 和 筛选条
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>员工</title>
    <%--引入相应的css与js--%>
    <%@include file="/WEB-INF/views/head.jsp" %>
    <script src="/js/model/employee.js"></script>
</head>
<body>

<%-- pagination:分页条支持 --%>
<table id="employeeGrid" class="easyui-datagrid"
       data-options="url:'/employee/page',fitColumns:true,singleSelect:true,
                fit:true,pagination:true,toolbar:'#gridTools'">
    <thead>
    <tr>
        <th data-options="field:'id',width:100">编码</th>
                <%--formatter:formatImage这是在调用employee.js里名为formatImage的函数--%>
        <th data-options="field:'headImage',width:100,formatter:formatImage">头像</th>
        <th data-options="field:'username',width:100">名称</th>
        <th data-options="field:'password',width:100">密码</th>
        <th data-options="field:'email',width:100">邮件</th>
        <th data-options="field:'age',width:100">年龄</th>
        <th data-options="field:'department',width:100,formatter:formatDept">部门</th>
    </tr>
    </thead>
</table>
<%--grid顶部工具栏--%>
<div id="gridTools" style="padding:5px;height:auto">
    <%--功能条--%>
    <div style="margin-bottom:5px">
        <a href="#" class="easyui-linkbutton" iconCls="icon-add" plain="true"></a>
        <a href="#" class="easyui-linkbutton" iconCls="icon-edit" plain="true"></a>
        <a href="#" class="easyui-linkbutton" iconCls="icon-save" plain="true"></a>
        <a href="#" class="easyui-linkbutton" iconCls="icon-cut" plain="true"></a>
        <a href="#" class="easyui-linkbutton" iconCls="icon-remove" plain="true"></a>
    </div>
     <%--查询条--%>
    <form id="searchForm">
        用户名: <input name="username" class="easyui-textbox" style="width:80px">
        邮件: <input name="email" class="easyui-textbox" style="width:80px">
        部门:                                          <%--panelHeight="auto"高度自适应--%>
        <input id="cc" name="departmentId" class="easyui-combobox"   panelHeight="auto"
               data-options="valueField:'id',textField:'name',url:'/util/depts'" />

        <a href="#" data-method="search" class="easyui-linkbutton" iconCls="icon-search">查询</a>
    </form>
</div>
</body>
</html>
  1. 在employee.js里加入以下JS代码
$(function () {

    //1.获取常用的一些组件
    var employeeGrid = $("#employeeGrid");
    var searchForm = $("#searchForm");

    //2.绑定相应的事件
    $("*[data-method]").on("click",function(){
        var methodName = $(this).data("method");
        window.itsource[methodName]();
    })
    
    itsource={
        search(){
            //serializeObject:拿到一个form中的所有数据,封装成json对象
            var params = searchForm.serializeObject();
            employeeGrid.datagrid("load",params);
        }
    }
})
  1. EmployeeQuery里添加部门的支持
public class EmployeeQuery extends BaseQuery{

    private String username;
    private String email;
    private Integer age;


    //部门
    private Long departmentId;


    @Override
    public Specification createSpec() {
        Specification<Employee> specification = Specifications.<Employee>and()
                .like(StringUtils.isNotBlank(username),"username", "%"+username+"%")
                .like(StringUtils.isNotBlank(email),"email", "%"+email+"%")
                
                //eq是等于的意思
                .eq(departmentId!=null,"department.id", departmentId)


                .gt(age != null,"age", age)
                .build();
        return specification;
    }
}

好了,就这样,高级查询就完成了 老规矩Tomcat测试 http://localhost/employee/index

总结
今天学了Spring Data Jpa扩展还有从数据库到前台的整个流程,其中也包括一些前台数据到后台与后台数据到前台数据不匹配的情况处理,也有easyui的一些知识点在里面

其中自认为重要的两个重要的点:
一是后台数据到前台响应不兼容通过把前台需要的数据封装到java的某个类中,再返回的方式非常的巧妙

二是懒加载出现no Session和No serializer问题的解决办法也很实用,以后遇到这种类似的问题也就知道怎么解决了

好了,今天就到这儿了,咱们下次再见吧。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值