今日内容
- 合同管理
- 货代整体流程
- 报运单管理
- webservice
- Apache的CXF
第一章 合同管理
1. 需求说明
实现合同管理列表的查询,只查询购销合同状态为已提交(state=1)
的状态的数据
2. ExportController
在export_manager_web
模块下的com.itheima.web.controller.cargo
包下创建ExportController
"/cargo/export") (
public class ExportController extends BaseController {
private ContractService contractService;
/**
* 已提交状态的合同列表查询
*/
"/contractList", name = "已提交状态的合同列表查询") (value =
public String contractList(
@RequestParam(defaultValue = "1", name = "page") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
ContractExample contractExample = new ContractExample();
//1 封装条件
ContractExample.Criteria criteria = contractExample.createCriteria();
criteria.andCompanyIdEqualTo(getCompanyId());
//状态提交
criteria.andStateEqualTo(1);
PageInfo pageInfo = contractService.findByPage(pageNum, pageSize,contractExample);
request.setAttribute("page", pageInfo);
return "/cargo/export/export-contractList";
}
}
第二章 货代整体流程(重点)
1. 货代整体流程说明
平台的大体流程是这样的: 合同签订–电子海关报运–货物装箱–委托运输–发票催款–财务记账
2. 打断设计思想
当关联查询的层级大于4层时,就要考虑打断设计,这样可以借助跳跃查询实现快速查询。
- 一对一:多张表共用主键(id)
- 一对多:在主表中通过创建一个打断字段,存储内容是从表的主键(id)集合
第三章 报运单管理(重点)
1. 需求分析
1.1 需求描述
SaaS货代平台是通过国际物流运输把货物运国外,这个过程需要经过海关人员的审批。
所以公司对于出口的产品就要进行出口报运,就需要形成出口报运单,将来公司的报运人员,需要拿着出口报运单到海关进行审批。
而出口报运单需要打印出来,打印的数据来自于数据库表。
1.2 数据模型分析
2. 导入资源
实体 -> export_domain\src\main\java\com\itheima\domain\cargo
dao接口->export_dao\src\main\java\com\itheima\dao\cargo
service接口->export_cargo_interface\src\main\java\com\itheima\service\cargo
service实现->export_cargo_service\src\main\java\com\itheima\service\cargo\impl
3. 报运单列表
修改ExportController, 生产报运单列表
/**
* 报运单列表查询
*/
"/list", name = "报运单列表查询") (value =
public String list(
@RequestParam(defaultValue = "1", name = "page") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
ExportExample exportExample = new ExportExample();
//1 封装条件
exportExample.createCriteria().andCompanyIdEqualTo(getCompanyId());
PageInfo pageInfo = exportService.findByPage(pageNum, pageSize,exportExample);
request.setAttribute("page", pageInfo);
return "/cargo/export/export-list";
}
4. 新增报运单
4.1 跳转生成报运单页面
修改ExportController, 跳转的到新增方法
"/toExport", name = "跳转报运单新增页面") (value =
public String toAdd(String id) {
//回显合同id集合
request.setAttribute("id", id);
return "/cargo/export/export-toExport";
}
4.2 生成报运单
4.2.1 ExportController
"/edit", name = "报运单新增") (value =
public String edit(Export export) {
if (StringUtils.isEmpty(export.getId())) {
//1. 设置主键
export.setId(UUID.randomUUID().toString());
//2. 设置企业信息
export.setCompanyId(getCompanyId());
export.setCompanyName(getCompanyName());
//3.制单时间
export.setInputDate(new Date());
//4. 设置当前合同的状态
export.setState(0);//草稿
exportService.save(export);
} else {
exportService.update(export);
}
//重定向到list方法
return "redirect:/cargo/export/list.do";
}
4.2.2 ExportServiceImpl
//保存
public void save(Export export) {
// 通过传入的参数获取合同id,合同id可以是数组
List<String> contractIdList = Arrays.asList(export.getContractIds().split(","));
/**
* 查询合同信息,封装报运单信息
*/
// 创建合同查询实体
ContractExample contractExample = new ContractExample();
// 将id参数传入到查询实体中
contractExample.createCriteria().andIdIn(contractIdList);
// 将查询到数据封装到list中
List<Contract> contractList = contractDao.selectByExample(contractExample);
// 拼接信息
StringBuilder stringBuilder = new StringBuilder();
Integer proNum = 0;
Integer extNum = 0;
for (Contract contract : contractList) {
stringBuilder.append(contract.getContractNo()).append(" ");
proNum += contract.getProNum();
extNum += contract.getExtNum();
}
// 设置报运单的合同号字符串
export.setCustomerContract(stringBuilder.toString());
// 设置报运单的合同的商品数
export.setProNum(proNum);
// 设置报运单的合同的附件数
export.setExtNum(extNum);
// 保存报运单
exportDao.insertSelective(export);
/**
* @author mryhl
* 查询合同货物信息,封装报运单货物信息
*/
// 查询货物
ContractProductExample contractProductExample = new ContractProductExample();
// 封装查询条件
contractProductExample.createCriteria().andContractIdIn(contractIdList);
// 查询货物
List<ContractProduct> contractProductList = contractProductDao.selectByExample(contractProductExample);
// 封装数据
for (ContractProduct contractProduct : contractProductList) {
// 订单商品实体
ExportProduct exportProduct = new ExportProduct();
BeanUtils.copyProperties(contractProduct,exportProduct);
// 生成id
exportProduct.setId(UUID.randomUUID().toString());
// 设置报运单的id
exportProduct.setExportId(export.getId());
// 保存数据
exportProductDao.insertSelective(exportProduct);
}
/**
* @author mryhl
* 查询合同附件信息,封装报运单附件信息
*/
// 报运单附件实体
ExtCproductExample extCproductExample = new ExtCproductExample();
// 查询当前报运单的附件
extCproductExample.createCriteria().andContractIdIn(contractIdList);
// 查询数据库
List<ExtCproduct> extCproductList = extCproductDao.selectByExample(extCproductExample);
//数据封装
for (ExtCproduct extCproduct : extCproductList) {
// 创建附件实体
ExtEproduct extEproduct = new ExtEproduct();
BeanUtils.copyProperties(extCproduct,extEproduct);
extEproduct.setId(UUID.randomUUID().toString());
extEproduct.setExportId(export.getId());
// 保存数据
extEproductDao.insertSelective(extEproduct);
}
}
5. 修改报运单
5.1 跳转修改页面
修改ExportController, 跳转到修改页面,传递当前报运单信息和当前报运单的商品信息
/**
* 跳转到修改
*/
"/toUpdate", name = "跳转报运单修改编辑页面") (value =
public String toUpdate(String id) {
//1. 根据id查询当报运单信息
Export export = exportService.findById(id);
request.setAttribute("export",export);
//2. 当前报运单下的货物
List<ExportProduct> exportProductList = exportProductService.findByExportId(id);
request.setAttribute("eps",exportProductList);
//3. 转发到修改页面
return "/cargo/export/export-update";
}
5.2 修改报运单
5.2.1 ExportController
"/edit", name = "报运单新增") (value =
public String edit(Export export) {
if (StringUtils.isEmpty(export.getId())) {
//1. 设置主键
export.setId(UUID.randomUUID().toString());
//2. 设置企业信息
export.setCompanyId(getCompanyId());
export.setCompanyName(getCompanyName());
//3.制单时间
export.setInputDate(new Date());
//4. 设置当前合同的状态
export.setState(0);//草稿
exportService.save(export);
} else {
exportService.update(export);
}
//重定向到list方法
return "redirect:/cargo/export/list.do";
}
5.2.2 ExportServiceImpl
//更新
public void update(Export export) {
//1. 修改报运单信息
exportDao.updateByPrimaryKeySelective(export);
for (ExportProduct exportProduct : export.getExportProducts()) {
//2. 修改报运单下的货物信息
exportProductDao.updateByPrimaryKeySelective(exportProduct);
}
}
6. 报运单的删除(作业)
6.1 ExportController
/**
* 删除功能
*/
"/delete", name = "报运单删除") (value =
public String delete(String id) {
//调用service删除
exportService.delete(id);
//重定向到list方法
return "redirect:/cargo/export/list.do";
}
6.2 ExportServiceImpl
//删除
public void delete(String id) {
// 查询当前报运单下的货物信息
ExportProductExample exportProductExample = new ExportProductExample();
exportProductExample.createCriteria().andExportIdEqualTo(id);
List<ExportProduct> exportProductList = exportProductDao.selectByExample(exportProductExample);
// 查询当前报运单下附件的信息
ExtEproductExample extEproductExample = new ExtEproductExample();
extEproductExample.createCriteria().andExportIdEqualTo(id);
//查询到的附件信息
List<ExtEproduct> extEproductList = extEproductDao.selectByExample(extEproductExample);
// 删除报运单下的货物信息
for (ExportProduct exportProduct : exportProductList) {
exportProductDao.deleteByPrimaryKey(exportProduct.getId());
}
// 删除附件
for (ExtEproduct extEproduct : extEproductList) {
extEproductDao.deleteByPrimaryKey(extEproduct.getId());
}
// 删除报运单
exportDao.deleteByPrimaryKey(id);
}
第四章 WebService(了解)
1. 简介
WebService是一种跨编程语言和跨操作系统平台的远程调用技术
跨编程语言:是指服务端、客户端程序的编程语言可以不同
跨操作系统:是指服务端、客户端可在不同的操作系统上运行
远程调用技术:远程调用是指一台设备上的程序A可以调用另一台设备上的方法B 比如:支付时调用微信提供的支付接口
2. 实现规范
JAVA 中共有三种WebService 规范,分别是JAX-WS、JAX-RS、JAXM&SAAJ(废弃)。
JAX-WS:是早期出现的WebService规范,通过SOAP协议传输标。
注:SOAP 是http+xml,通过http的形式发送标准格式的XML文件数据。只能通过客户端代码调用(固定)JAX-RS: JAVA 针对REST(Representation State Transfer)风格制定的一套Web服务规范。
注:REST 是一种软件架构风格,rest服务采用HTTP做传输协议。可以通过浏览器获取数据(灵活)
第五章 Apache的CXF(重点)
1. 简介
Apache CXF 是一个开源的 Web Services 框架。与spring整合后可以轻松实现 Web Services 的发布和使用,并支持SOAP协议和REST风格,操作简单,灵活部署。官网地址:http://cxf.apache.org/
2. 环境搭建
创建webservice_parent
聚合父工程,统一管理依赖
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.0.1</version>
</dependency>
<!-- cxf 进行rs开发 必须导入 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 日志引入 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
<!-- 客户端 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 扩展json提供者 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-extension-providers</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 转换json工具包,被extension providers 依赖 -->
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>1.3.7</version>
</dependency>
<!-- spring 核心 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!-- spring web集成 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!-- spring 整合junit -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!-- junit 开发包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 设置编译版本为1.8 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
3. 基于JAX-WS规范的入门( 了解 )
3.1 JAX-WS规范三要素(笔试)
- SOAP: http+xml 基于HTTP协议,采用XML格式,用来传递信息
- WSDL: 使用说明书(用来描述如何访问具体的服务)
- UDDI: 产品目录(企业将自己提供的WebService注册在UDDI,也可以使用别的企业在UDDI注册的WebService,从而达到资源共享)
3.2 服务端
3.2.1 创建一个web模块(ws_server)
3.2.2 创建接口和实现类
/**
* @author mryhl
* 当写了此注解时,表明当前接口是一个webservice接口
*/
public interface WeatherService {
/**
* 根据城市名称,获取城市天气
*/
String getWeatherByCityName(String cityName);
}
public class WeatherServiceImpl implements WeatherService {
/**
* 此处就不经过数据库了,为的是演示webservice的用法
*/
public String getWeatherByCityName(String cityName) {
if ("北京".equals(cityName)) {
return "万里无云";
} else if ("上海".equals(cityName)) {
return "小雨";
} else if ("深圳".equals(cityName)) {
return "晴";
}
return "未知";
}
}
3.2.3 加入配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<!--
提供的webService基于jaxws的服务端
-->
<jaxws:server address="/weatherServiceImpl" serviceClass="com.itheima.service.WeatherServiceImpl"></jaxws:server>
</beans>
3.2.4 加入web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-cxf-server.xml</param-value>
</context-param>
<!-- CXF框架的核心控制器:CXFServlet -->
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>4</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
</web-app>
3.2.5 部署
生成的wsdl的地址: http://localhost:5000/ws/weatherService?wsdl
3. 3 客户端
3.3.1 创建一个web模块(ws_client)
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>webservice_parent</artifactId>
<groupId>com.itheima</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ws_client</artifactId>
</project>
3.3.2 使用wsdl生成客户端的程序代码
E:\code\webservice_parent\ws_client\src\main\java>wsimport -s ./ http://localhost:5000/ws/weatherService?wsdl
正在解析 WSDL...
正在生成代码...
正在编译代码...
3.3.3 加入配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<!--
提供的webService基于jaxws的服客户端
-->
<jaxws:client id="weatherService" address="http://localhost:5000/ws/weatherService?wsdl"
serviceClass="com.itheima.service.WeatherService">
</jaxws:client>
</beans>
3.3.4 加入测试的类
/**
* @description:
* @author: mryhl
* @date: Created in 2020/10/20 18:10
* @version: 1.1
*/
public class App {
public static void main(String[] args) {
// 启动spring
ClassPathXmlApplicationContext act = new ClassPathXmlApplicationContext("applicationContext-cxf-client.xml");
// 获取代理对象
WeatherService weatherService = (WeatherService) act.getBean("weatherService");
// 调用对象方法
System.out.println(weatherService.getWeatherByCityName("北京"));
System.out.println(weatherService.getWeatherByCityName("上海"));
System.out.println(weatherService.getWeatherByCityName("唐山"));
}
}
4. 基于JAX-RS规范的入门( 重点 )
4.1 服务端
4.1.1 创建一个web模块(rs_server)
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>webservice_parent</artifactId>
<groupId>com.itheima</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>rs_server</artifactId>
</project>
4.1.2 创建实体类
4.1.3 创建接口和实现类
import com.itheima.domain.User;
import javax.ws.rs.*;
import java.util.List;
//@Path 访问路径, 这个跟SpringMVC中的@RequestMapping的path属性
//@POST @PUT @GET @DELETE 用于标识此操作是增删改查中的哪一个, 这个跟SpringMVC中的@RequestMapping的method属性
//@Consumes 指定此方法可以接收的请求的数据类型
//@Produces 指定此方法可以返回的响应的数据类型,默认是XML
// @Path("/userService")
public interface UserService {
"/user") (
"application/xml", "application/json"}) ({
public void saveUser(User user);
"/user") (
"application/xml", "application/json"}) ({
public void updateUser(User user);
"/user") (
"application/xml", "application/json"}) ({
public List<User> findAllUsers();
"/user/{id}") (
"application/xml", "application/json"}) ({
"application/xml", "application/json"}) ({
public User finUserById(@PathParam("id") Integer id);
"/user/{id}") (
"application/xml", "application/json"}) ({
public void deleteUser(@PathParam("id") Integer id);
}
import com.itheima.domain.User;
import java.util.ArrayList;
import java.util.List;
public class UserServiceImpl implements UserService {
public void saveUser(User user) {
System.out.println("save user:" + user);
}
public void updateUser(User user) {
System.out.println("update user:" + user);
}
public List<User> findAllUsers() {
List<User> users = new ArrayList<>();
User user1 = new User();
user1.setId(1);
user1.setUsername("小明");
user1.setCity("北京");
users.add(user1);
User user2 = new User();
user2.setId(2);
user2.setUsername("小丽");
user2.setCity("上海");
users.add(user2);
return users;
}
public User finUserById(Integer id) {
if (id == 1) {
User user1 = new User();
user1.setId(1);
user1.setUsername("小明");
user1.setCity("北京");
return user1;
}
return null;
}
public void deleteUser(Integer id) {
System.out.println("delete user id :" + id);
}
}
4.1.4 加入配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">
<!--
提供的webService基于jaxrs的服务端
-->
<jaxrs:server address="/userService" serviceClass="com.itheima.service.UserServiceImpl"></jaxrs:server>
</beans>
4.1.5 加入web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-rs.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- CXF的核心控制器 -->
<servlet>
<servlet-name>cxfServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cxfServlet</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
</web-app>
4.1.6 部署
4.2 浏览器客户端
不需要什么wsdl说明书,直接通过http协议发送请求,获得xml或json数据,非常简单…
http://localhost:5001/ws/userService/user
4.3 程序客户端
import com.itheima.domain.User;
import org.apache.cxf.jaxrs.client.WebClient;
import org.junit.Test;
import java.util.Collection;
import java.util.List;
public class App {
public void testFindAll() {
//WebClient默认只能解析XML格式的数据
// User user = WebClient.create("http://localhost:5001/ws/userService/user/1").get(User.class);
// System.out.println(user);
Collection<? extends User> users = WebClient.create("http://localhost:5001/ws/userService/user").getCollection(User.class);
for (User user : users) {
System.out.println(user);
}
}
public void testDelete() {
//WebClient默认只能解析XML格式的数据
WebClient.create("http://localhost:5001/ws/userService/user/1").delete();
}
public void testPost() {
//WebClient默认只能解析XML格式的数据
User user = new User();
user.setId(1);
user.setUsername("xiaoming");
user.setCity("tj");
WebClient.create("http://localhost:5001/ws/userService/user").post(user);
}
}