日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

基于ssm的航空订票系统

發(fā)布時(shí)間:2023/12/10 windows 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于ssm的航空订票系统 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

基于ssm的航空訂票系統(tǒng)

一、技術(shù)棧

? 前端
? vue全家桶、element-ui組件庫(kù)、moment.js插件
? 后端
? springboot + springmvc+ mybatis

二、功能描述

本系統(tǒng)是基于B/S架構(gòu)的航空訂票系統(tǒng)

系統(tǒng)分為三大用戶–乘客、航空公司、后臺(tái)管理員,本次課程設(shè)計(jì)主要實(shí)現(xiàn)了乘客界面,包括購(gòu)票、選座、充值、退款、改簽等

三、技術(shù)框架

1、界面設(shè)計(jì)

Vue是一套用于構(gòu)建用戶界面的漸進(jìn)式框架。與其它大型框架不同的是,Vue 被設(shè)計(jì)為可以自底向上逐層應(yīng)用。Vue 的核心庫(kù)只關(guān)注視圖層,不僅易于上手,還便于與第三方庫(kù)或既有項(xiàng)目整合。

上面這段官方解釋的意思是,vue提供了一種組件化設(shè)計(jì)的方式,也就是說(shuō),你可以在單個(gè)vue對(duì)象中構(gòu)建起實(shí)現(xiàn)某些功能compopent,再在下一個(gè)vue中將它們組裝,最后在一個(gè)vue中展示。有過(guò)面向?qū)ο缶幊探?jīng)歷的程序員很容易接受這種設(shè)計(jì)方式,就像手寫(xiě)一個(gè)自己的class,然后再別的類(lèi)中引用類(lèi)實(shí)例和方法一樣——就連引入這個(gè)行為使用的也是同一個(gè)關(guān)鍵字import

Element,一套為開(kāi)發(fā)者、設(shè)計(jì)師和產(chǎn)品經(jīng)理準(zhǔn)備的基于 Vue 2.0 的桌面端組件庫(kù)

Element UI 對(duì)于新手前端設(shè)計(jì)師來(lái)說(shuō)是福音,它自帶的一系列標(biāo)簽和組件可以幫助那些為JavaScript繁瑣而頭疼的編程者們開(kāi)辟一個(gè)的新天地。只要基礎(chǔ)程度的審美,人人都可以設(shè)計(jì)出一套簡(jiǎn)潔好看的界面。

這些組件可以通過(guò)Attribute、Event和Methods標(biāo)簽進(jìn)行個(gè)性化的設(shè)置,同時(shí)也在很大程度上簡(jiǎn)化了js函數(shù)的寫(xiě)法

2、前后端通信

引入axios插件后,在函數(shù)中可以通過(guò)axios對(duì)象向目標(biāo)端口發(fā)送請(qǐng)求并執(zhí)行回調(diào),例如向8181端口發(fā)送一個(gè)post請(qǐng)求

this.$axios.post("http://localhost:8181/findAll").then(res => {})

后端可以通過(guò)設(shè)置一個(gè)跨域類(lèi)CrosConfig來(lái)接收前端請(qǐng)求

import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration public class CrosConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**")//攔截所有請(qǐng)求.allowedOrigins("*").allowedMethods("GET","HEAD","POST","PUT","DELETE")//攔截所有類(lèi)型.allowCredentials(true).maxAge(3600)//最大線程數(shù).allowedHeaders("*");//允許所有請(qǐng)求頭} }

也有在src/resource/mybatis-config.xml中配置跨域的方法,這邊不贅述

映射寫(xiě)法

主流有兩種方法,一種是REST風(fēng)格,一種是直接發(fā)送json的寫(xiě)法

  • 簡(jiǎn)單來(lái)說(shuō),REST風(fēng)格將發(fā)送的數(shù)據(jù)拼接進(jìn)請(qǐng)求里,通過(guò) “/” 隔開(kāi),在后臺(tái)用 @RequestMapping 注解完成方法映射 @PathVariable注解直接賦值到確定數(shù)據(jù)類(lèi)型里

如:前端

this.$axios.post("http://localhost:8181/login/passenger/"+that.loginform.passengername+"/"+that.loginform.password)

后端

@RequestMapping (value = "/passenger/{passengername}/{password}",method = RequestMethod.POST,produces = {"application/json;charset=UTF-8"}) public String passengerlogin(@PathVariable("passengername") String passengername,@PathVariable("password") String password)
  • 另一種向后臺(tái)直接發(fā)送數(shù)據(jù)的則是要用*@RequestBody*,把json表封裝成類(lèi)實(shí)例,再調(diào)用get方法取數(shù)據(jù)

如:前端

this.$axios.post("http://localhost:8181/order/refund", row)

后端

@RequestMapping (value = "refund", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"}) public String refundOrder(@RequestBody OrderInfo orderInfo)

在數(shù)據(jù)量較小的情況下,REST風(fēng)格要更加簡(jiǎn)潔干練

3、持久層

現(xiàn)在使用最廣泛的兩種持久層框架是JPA和mybatis,這兩者都有各自忠實(shí)的使用者,孰優(yōu)孰劣也不是我這樣的技術(shù)小白講得清楚的,不過(guò)我的建議是,如果你剛剛接觸持久層框架而整糾結(jié)于二者的選擇,不妨就照著這篇博客試試mybatis,在初級(jí)階段,它絕不比JPA更復(fù)雜,同時(shí)也能保證完成你的各項(xiàng)設(shè)計(jì)目標(biāo)。你可以在下一次實(shí)驗(yàn)中嘗試JPA,再來(lái)體會(huì)一下二者的區(qū)別

MyBatis 是一款優(yōu)秀的持久層框架,它支持自定義 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射。MyBatis 免除了幾乎所有的 JDBC 代碼以及設(shè)置參數(shù)和獲取結(jié)果集的工作。MyBatis 可以通過(guò)簡(jiǎn)單的 XML 或注解來(lái)配置和映射原始類(lèi)型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 對(duì)象)為數(shù)據(jù)庫(kù)中的記錄。

如官方文檔所言,持久層框架的價(jià)值有二:一是封裝JDBC代碼,省去繁瑣重復(fù)的操作,使人的工作能集中到sql代碼的書(shū)寫(xiě)和數(shù)據(jù)庫(kù)設(shè)計(jì)上來(lái);二是維持POJO,使數(shù)據(jù)以對(duì)象的形式長(zhǎng)久穩(wěn)定地存在于程序運(yùn)行過(guò)程中,提升了數(shù)據(jù)交互的效率

簡(jiǎn)單的sql語(yǔ)句可以通過(guò)注解直接在方法上書(shū)寫(xiě),復(fù)雜查詢語(yǔ)句或者大段大段的sql則適合接口 + .xml文檔的方式,為了統(tǒng)一形式,對(duì)初學(xué)者我更加推薦把所有的sql都寫(xiě)在xml文檔中的方法

mybatis將數(shù)據(jù)實(shí)體、接口方法和sql實(shí)現(xiàn)xml聯(lián)動(dòng)的寫(xiě)法可以參照如下代碼

數(shù)據(jù)實(shí)體類(lèi)PassengerInfo

package com.oreki.ptss_rear.domain;import lombok.Data;@Data public class PassengerInfo {private Integer passengerId;private String passengerName;private String passengerPassword;private String passengerIdentity;private String passengerPhone;private Float passengerAccount; }

@Data注解來(lái)自于lombok插件,它能幫你隱式地生成Set、Get、ToString等方法(雖然也有g(shù)etter、setter的Constructor自動(dòng)生成器,不過(guò)減少顯式出現(xiàn)的代碼量總是好的)

另外,不同于JPA,mybatis不需要聲明數(shù)據(jù)實(shí)體類(lèi),也就不需要設(shè)置主鍵(對(duì)比于JPA的@Entity和@Id標(biāo)簽)

接口類(lèi)PassengerInfoMapper

package com.oreki.ptss_rear.mapper;import com.oreki.ptss_rear.domain.PassengerInfo; import org.apache.ibatis.annotations.Param; import java.util.List;public interface PassengerInfoMapper {int deleteByPrimaryKey(Integer passengerId);int insert(PassengerInfo record);int insertSelective(PassengerInfo record);int updateByPrimaryKeySelective(PassengerInfo record);int updateByPrimaryKey(PassengerInfo record);int updateByPrimaryKeyCharge(@Param(value = "passengerId") Integer passengerId,@Param(value = "passengerAccount") Float passengerAccount);List<PassengerInfo> getList();PassengerInfo selectByPassengerName(String passengerName);PassengerInfo selectByPrimaryKey(Integer passengerId);List<PassengerInfo> selectListByName(String searchtext); }

在接口類(lèi)中導(dǎo)入實(shí)體類(lèi)后就建立起了方法與實(shí)體數(shù)據(jù)的聯(lián)系

@Param是MyBatis所提供的,作為Dao層的注解,作用是用于傳遞參數(shù),從而可以與SQL中的的字段名相對(duì)應(yīng),解決了可讀性和直觀性的問(wèn)題

書(shū)寫(xiě)sql語(yǔ)句的xml文檔PassengerMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.oreki.ptss_rear.mapper.PassengerInfoMapper"><resultMap id="BaseResultMap" type="com.oreki.ptss_rear.domain.PassengerInfo"><id column="passenger_id" jdbcType="INTEGER" property="passengerId" /><result column="passenger_name" jdbcType="VARCHAR" property="passengerName" /><result column="passenger_password" jdbcType="VARCHAR" property="passengerPassword" /><result column="passenger_identity" jdbcType="VARCHAR" property="passengerIdentity" /><result column="passenger_phone" jdbcType="VARCHAR" property="passengerPhone" /><result column="passenger_account" jdbcType="REAL" property="passengerAccount" /></resultMap><sql id="Base_Column_List">passenger_id, passenger_name, passenger_password, passenger_identity,passenger_phone, passenger_account</sql><select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">select *from passenger_infowhere passenger_id = #{passengerId,jdbcType=INTEGER}</select><select id="getList" resultMap="BaseResultMap">select *from passenger_info</select><select id="selectByPassengerName" parameterType="java.lang.String" resultMap="BaseResultMap">select *from passenger_infowhere passenger_name = #{passengerName,jdbcType=VARCHAR}</select><select id="selectListByName" parameterType="java.lang.String" resultMap="BaseResultMap">select *from passenger_infowhere passenger_name like concat ('%',#{searchtext},'%')</select><delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">delete from passenger_infowhere passenger_id = #{passengerId,jdbcType=INTEGER}</delete><insert id="insert" parameterType="com.oreki.ptss_rear.domain.PassengerInfo">insert into passenger_info (passenger_id, avatar, passenger_name,passenger_password, passenger_gender, passenger_identity,passenger_phone, passenger_account, register_time)values (#{passengerId,jdbcType=INTEGER}, #{avatar,jdbcType=VARCHAR}, #{passengerName,jdbcType=VARCHAR},#{passengerPassword,jdbcType=VARCHAR}, #{passengerGender,jdbcType=VARCHAR}, #{passengerIdentity,jdbcType=VARCHAR},#{passengerPhone,jdbcType=VARCHAR}, #{passengerAccount,jdbcType=REAL}, #{registerTime,jdbcType=TIMESTAMP})</insert><insert id="insertSelective" parameterType="com.oreki.ptss_rear.domain.PassengerInfo">insert into passenger_info<trim prefix="(" suffix=")" suffixOverrides=","><if test="passengerId != null">passenger_id,</if><if test="avatar != null">avatar,</if><if test="passengerName != null">passenger_name,</if><if test="passengerPassword != null">passenger_password,</if><if test="passengerGender != null">passenger_gender,</if><if test="passengerIdentity != null">passenger_identity,</if><if test="passengerPhone != null">passenger_phone,</if><if test="passengerAccount != null">passenger_account,</if><if test="registerTime != null">register_time,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="passengerId != null">#{passengerId,jdbcType=INTEGER},</if><if test="avatar != null">#{avatar,jdbcType=VARCHAR},</if><if test="passengerName != null">#{passengerName,jdbcType=VARCHAR},</if><if test="passengerPassword != null">#{passengerPassword,jdbcType=VARCHAR},</if><if test="passengerGender != null">#{passengerGender,jdbcType=VARCHAR},</if><if test="passengerIdentity != null">#{passengerIdentity,jdbcType=VARCHAR},</if><if test="passengerPhone != null">#{passengerPhone,jdbcType=VARCHAR},</if><if test="passengerAccount != null">#{passengerAccount,jdbcType=REAL},</if><if test="registerTime != null">#{registerTime,jdbcType=TIMESTAMP},</if></trim></insert><update id="updateByPrimaryKeySelective" parameterType="com.oreki.ptss_rear.domain.PassengerInfo">update passenger_info<set><!--<if test="avatar != null">avatar = #{avatar,jdbcType=VARCHAR},</if>--><if test="passengerName != null">passenger_name = #{passengerName,jdbcType=VARCHAR},</if><if test="passengerPassword != null">passenger_password = #{passengerPassword,jdbcType=VARCHAR},</if><if test="passengerIdentity != null">passenger_identity = #{passengerIdentity,jdbcType=VARCHAR},</if><if test="passengerPhone != null">passenger_phone = #{passengerPhone,jdbcType=VARCHAR},</if><if test="passengerAccount != null">passenger_account = #{passengerAccount,jdbcType=REAL},</if></set>where passenger_id = #{passengerId,jdbcType=INTEGER}</update><update id="updateByPrimaryKey" parameterType="com.oreki.ptss_rear.domain.PassengerInfo">update Passenger_infoset avatar = #{avatar,jdbcType=VARCHAR},passenger_name = #{passengerName,jdbcType=VARCHAR},passenger_password = #{passengerPassword,jdbcType=VARCHAR},passenger_gender = #{passengerGender,jdbcType=VARCHAR},passenger_identity = #{passengerIdentity,jdbcType=VARCHAR},passenger_phone = #{passengerPhone,jdbcType=VARCHAR},passenger_account = #{passengerAccount,jdbcType=REAL},register_time = #{registerTime,jdbcType=TIMESTAMP}where passenger_id = #{passengerId,jdbcType=INTEGER}</update><update id="updateByPrimaryKeyCharge">update Passenger_infoset passenger_account = #{passengerAccount,jdbcType=REAL}where passenger_id = #{passengerId,jdbcType=INTEGER};</update></mapper>

頭兩行是一般xml文件的規(guī)范

標(biāo)簽通過(guò)namespace屬性,可以確定該文檔實(shí)現(xiàn)的是哪一個(gè)接口

標(biāo)簽,id屬性指定了當(dāng)前對(duì)應(yīng)集類(lèi)型,一般是BaseResultMap;type屬性指明了操作的數(shù)據(jù)庫(kù)Table和項(xiàng)目中的Entity實(shí)體的對(duì)應(yīng)關(guān)系。

resultMap內(nèi)部的標(biāo)簽說(shuō)明了主鍵,標(biāo)簽將Table中的列名和實(shí)體的對(duì)象名進(jìn)行對(duì)應(yīng)(注意MySql不區(qū)分大小寫(xiě))

4.MVC框架

模式Model—視圖View—控制器Controller(MVC)是上世紀(jì)出現(xiàn)的一種軟件設(shè)計(jì)模式,這一模式早期發(fā)展(Model1和Model2時(shí)代)后,現(xiàn)在有如SpringMVC這樣的方案

這對(duì)僅有過(guò)小型程序編程經(jīng)驗(yàn)的學(xué)習(xí)者來(lái)說(shuō)是理解大型軟件模塊間相互作用和交流的一種優(yōu)秀模式,結(jié)構(gòu)松散、耦合、與 Spring 無(wú)縫集成等特性讓其大放異彩

四、功能展示


主界面,進(jìn)行搜索或點(diǎn)擊圖片都可進(jìn)入購(gòu)票詳情頁(yè)


機(jī)票詳情


機(jī)票檢索


錢(qián)包界面


訂單中心,可進(jìn)行改簽/退票等操作


改簽界面,多退少補(bǔ)

五、DEBUG記錄

Tip1

數(shù)據(jù)庫(kù):實(shí)體類(lèi)中的變量名(包括類(lèi)名)與數(shù)據(jù)庫(kù)中的字段名(包括表名)匹配時(shí),要注意這樣一條規(guī)則,java變量大小寫(xiě)敏感,可以在一個(gè)長(zhǎng)變量名中通過(guò)大寫(xiě)字母分隔單詞;數(shù)據(jù)庫(kù)大小寫(xiě)不敏感,通過(guò)數(shù)據(jù)庫(kù)管理工具看到的顯示大小寫(xiě)只是一種展示,變量名映射為字段名、類(lèi)名映射為表名,大寫(xiě)分隔轉(zhuǎn)為橫杠分隔

e.g 錯(cuò)誤×:變量passengerId對(duì)應(yīng)數(shù)據(jù)庫(kù)字段passengerId 正確√:passengerId → passenger_id
修改圖片路徑報(bào)錯(cuò)
Module not found Can't resolve './src/assets/img/Aurora.jpg' in 'C:\Users\HP\myproject\passenger_ticket_sell\src\views\passenger\home'

解決辦法:項(xiàng)目?jī)?nèi)絕對(duì)路徑改寫(xiě)為相對(duì)路徑

第一次改為相對(duì)路徑編譯成功后,使用絕對(duì)路徑或者@標(biāo)簽都找得到資源,這可能是因?yàn)橄纫?cè)一次?不太清楚

url("src/assets/img/Paris.jpg");url("../../../assets/img/Paris.jpg");
前端500

有可能使因?yàn)楹笈_(tái)沒(méi)有傳回?cái)?shù)據(jù),這時(shí)如果出現(xiàn)后端接收的json數(shù)據(jù)全為null的情況,當(dāng)接收體是對(duì)象時(shí),需要@RequestBody標(biāo)簽,即>json通過(guò)該標(biāo)簽和對(duì)象內(nèi)變量建立聯(lián)系(同名)

如果后端以參數(shù)形式接收數(shù)據(jù)的話,建議REST風(fēng)格

josn直接裝配到后端參數(shù)解決ing


動(dòng)態(tài)讀取圖片(數(shù)據(jù)庫(kù)路徑)

img屬性

<img@click="showdetial(item.ticketId)":src="imgUrl(item.ticketImg)"width="250px"height="200px" />

方法中返回動(dòng)態(tài)的路徑,require后必須接路徑,所有需要有"…/…/…/assets/img/“前綴,拼接起來(lái)解釋成路徑,
不能直接通過(guò)img傳入”…/…/…/assets/img/test.jpg"再require(img),這樣解釋成String,會(huì)報(bào)錯(cuò)

imgUrl(img){return require("../../../assets/img/" + img); }

總結(jié)

以上是生活随笔為你收集整理的基于ssm的航空订票系统的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。