生企業(yè)推薦系統(tǒng)實(shí)戰(zhàn)指南)
簡(jiǎn)介本資源是一套完整的Java畢業(yè)設(shè)計(jì)項(xiàng)目——基于SSM與Vue的大學(xué)生企業(yè)推薦系統(tǒng)面向計(jì)算機(jī)專業(yè)本科生及Java初學(xué)者解決校園招聘場(chǎng)景中學(xué)生、企業(yè)與管理員三方信息對(duì)接低效問題。項(xiàng)目采用B/S架構(gòu)涵蓋管理員、學(xué)生、企業(yè)三類角色功能模塊并新增實(shí)時(shí)資訊推送能力提升信息獲取效率。壓縮包共843個(gè)文件含127個(gè)Java后端邏輯文件、48個(gè)Vue前端組件、156個(gè)JS交互腳本、163個(gè)SVG圖標(biāo)資源、79個(gè)GIF動(dòng)效素材及配套SQL、PPT、LW文檔與MP4演示視頻整體大小74.01MB結(jié)構(gòu)清晰、模塊解耦度高。已有236人學(xué)習(xí)下載資源經(jīng)實(shí)測(cè)可在JDK1.8Tomcat7MySQL5.7環(huán)境下穩(wěn)定運(yùn)行附帶3個(gè)批處理腳本安裝/啟動(dòng)/構(gòu)建及完整開發(fā)環(huán)境配置說明便于快速部署與二次開發(fā)。1. 為什么一個(gè)“大學(xué)生企業(yè)推薦系統(tǒng)”要硬套 SSM Vue——它真能跑通就業(yè)場(chǎng)景的冷啟動(dòng)問題你手頭這份標(biāo)著“java畢業(yè)設(shè)計(jì)之ssm大學(xué)生企業(yè)推薦系統(tǒng)ssmvue源碼LWPPT視頻.zip”的壓縮包不是又一個(gè)復(fù)制粘貼的教務(wù)系統(tǒng)仿制品。它背后藏著一個(gè)被多數(shù)課程設(shè)計(jì)忽略的現(xiàn)實(shí)矛盾高校就業(yè)辦推的崗位千篇一律學(xué)生簡(jiǎn)歷石沉大海企業(yè)HR篩人像在 haystack 里找 needle。而這個(gè)系統(tǒng)試圖用最樸素的技術(shù)?!猄SMSpring SpringMVC MyBatis打底、Vue 做交互層——去解決一個(gè)具體問題讓沒有實(shí)習(xí)經(jīng)歷、項(xiàng)目經(jīng)驗(yàn)單薄、技能標(biāo)簽?zāi):膽?yīng)屆生也能基于課程成績(jī)、技能證書、社團(tuán)角色、甚至選修課偏好匹配到真正愿意給新人機(jī)會(huì)的中小型企業(yè)崗位。它不追求算法有多炫但必須能真實(shí)跑在本地 Tomcat 上、數(shù)據(jù)庫(kù)能導(dǎo)入真實(shí)院校數(shù)據(jù)、前端能完成“學(xué)生填表→系統(tǒng)打分→企業(yè)端查看匹配度→雙向意向確認(rèn)”閉環(huán)。這不是玩具 Demo而是畢業(yè)答辯前最后一道實(shí)操關(guān)卡你得讓它動(dòng)起來、改得動(dòng)、講得清、答得住。尤其當(dāng)答辯老師問“你這個(gè)推薦邏輯和智聯(lián)招聘的協(xié)同過濾差在哪”你得拿出RecommendService.java里那幾行帶注釋的加權(quán)規(guī)則而不是背八股文。2. 搭建底層骨架SSM 三件套怎么配才不翻車——從 pom.xml 到 web.xml 的血淚校驗(yàn)清單SSM 不是三個(gè)框架簡(jiǎn)單堆砌而是三層職責(zé)咬合Spring 管 Bean 和事務(wù)、SpringMVC 接口路由、MyBatis 操作數(shù)據(jù)庫(kù)。畢業(yè)設(shè)計(jì)里最容易崩的就是這層耦合——明明代碼沒改換個(gè) JDK 版本或 Tomcat 就 404明明 SQL 在 Navicat 里跑得飛起Java 里查出來卻是 null。下面這套配置是我壓箱底的校驗(yàn)清單專治“環(huán)境一換就掛”。2.1 Maven 依賴版本鎖死別信“最新版最穩(wěn)”信測(cè)試過的組合畢業(yè)設(shè)計(jì)最怕依賴沖突。Spring 5.3.x 和 MyBatis 3.4.x 是目前高校機(jī)房、學(xué)生筆記本上兼容性最好的組合JDK 8 Tomcat 8.5/9.0。pom.xml 中必須顯式鎖定禁止用RELEASE或LATEST!-- Spring 核心 -- dependency groupIdorg.springframework/groupId artifactIdspring-context/artifactId version5.3.30/version /dependency !-- SpringMVC -- dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version5.3.30/version /dependency !-- MyBatis -- dependency groupIdorg.mybatis/groupId artifactIdmybatis/artifactId version3.4.6/version /dependency !-- MyBatis-Spring 整合包關(guān)鍵很多翻車源于漏掉它 -- dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version1.3.2/version /dependency !-- 數(shù)據(jù)庫(kù)驅(qū)動(dòng)務(wù)必用 mysql-connector-java 5.1.478.x 驅(qū)動(dòng)在老 Tomcat 下常報(bào)時(shí)區(qū)錯(cuò)誤 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version5.1.47/version /dependency提示mybatis-spring是 SSM 能跑起來的“膠水”。沒有它Spring 容器根本不知道 MyBatis 的 SqlSessionFactory 存在哪Autowired注入 Mapper 會(huì)直接報(bào)NoSuchBeanDefinitionException。這是答辯現(xiàn)場(chǎng)高頻翻車點(diǎn)。2.2 web.xmlSpring 容器與 SpringMVC 容器的邊界必須劃清很多同學(xué)把所有配置塞進(jìn)一個(gè)applicationContext.xml結(jié)果 Controller 里Autowired的 Service 總是 null。根源在于Spring 容器加載 Service/Dao和 SpringMVC 容器加載 Controller是父子關(guān)系子容器能訪問父容器 Bean反之不行。web.xml 必須分兩步加載!-- 1. 加載根容器只掃 Service, Repository -- context-param param-namecontextConfigLocation/param-name param-valueclasspath:applicationContext.xml/param-value /context-param listener listener-classorg.springframework.web.context.ContextLoaderListener/listener-class /listener !-- 2. 加載 MVC 容器只掃 Controller -- servlet servlet-namespringmvc/servlet-name servlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-class init-param param-namecontextConfigLocation/param-name param-valueclasspath:springmvc-servlet.xml/param-value /init-param load-on-startup1/load-on-startup /servlet servlet-mapping servlet-namespringmvc/servlet-name url-pattern//url-pattern /servlet-mappingapplicationContext.xml里context:component-scan的 base-package 只寫com.xxx.service, com.xxx.daospringmvc-servlet.xml里只寫com.xxx.controller。錯(cuò)掃一個(gè)包就會(huì)出現(xiàn)“Service 被加載了兩次”或“Controller 找不到 Service”。2.3 MyBatis 映射文件里的坑resultMap 不寫 ID查出來全是 null學(xué)生常把UserMapper.xml當(dāng) SQL 文件寫漏掉最關(guān)鍵的resultMap聲明。例如學(xué)生表有student_id,name,major字段實(shí)體類屬性是id,name,major若不顯式映射!-- 錯(cuò)誤沒 resultMapMyBatis 默認(rèn)按字段名屬性名匹配student_id ≠ id -- select idselectStudent resultTypeStudent SELECT student_id, name, major FROM student /select !-- 正確必須用 resultMap 告訴 MyBatis 字段和屬性怎么對(duì) -- resultMap idStudentResultMap typeStudent id propertyid columnstudent_id/ result propertyname columnname/ result propertymajor columnmajor/ /resultMap select idselectStudent resultMapStudentResultMap SELECT student_id, name, major FROM student /selectid標(biāo)簽不是可選的——它標(biāo)記主鍵影響一級(jí)緩存命中率。漏寫會(huì)導(dǎo)致同一 ID 查兩次返回兩個(gè)不同對(duì)象內(nèi)存泄漏隱患。3. 推薦邏輯落地不用機(jī)器學(xué)習(xí)靠規(guī)則加權(quán)也能做出“可解釋”的匹配畢業(yè)設(shè)計(jì)里最常被質(zhì)疑的點(diǎn)“你這叫推薦系統(tǒng)不就是個(gè) if-else” —— 但恰恰是這種“可解釋性”才是企業(yè)端愿意看懂、愿意信任的關(guān)鍵。這個(gè)系統(tǒng)沒用 Spark 或 Python全靠 Java 寫的RecommendService實(shí)現(xiàn)三步加權(quán)基礎(chǔ)匹配專業(yè)對(duì)口學(xué)生專業(yè) ∈ 企業(yè)招聘專業(yè)列表 → 30 分能力強(qiáng)化技能證書如英語(yǔ)四級(jí)、計(jì)算機(jī)二級(jí)、Java 認(rèn)證→ 每項(xiàng) 10 分行為偏好選修課記錄如選過《企業(yè)資源規(guī)劃》《人力資源管理》→ 每門 5 分最終得分 基礎(chǔ)分 × 0.4 能力分 × 0.35 行為分 × 0.25。所有權(quán)重可后臺(tái)配置答辯時(shí)能調(diào)參數(shù)、看變化。3.1 核心推薦方法calculateMatchScore()的完整實(shí)現(xiàn)Service public class RecommendServiceImpl implements RecommendService { Autowired private StudentMapper studentMapper; Autowired private EnterpriseMapper enterpriseMapper; // 權(quán)重配置實(shí)際項(xiàng)目中應(yīng)從數(shù)據(jù)庫(kù)或配置文件讀取 private final double BASE_WEIGHT 0.4; private final double SKILL_WEIGHT 0.35; private final double BEHAVIOR_WEIGHT 0.25; Override public ListEnterprise recommendEnterprises(Long studentId) { Student student studentMapper.selectById(studentId); ListEnterprise allEnterprises enterpriseMapper.selectAll(); return allEnterprises.stream() .map(enterprise - { double score calculateMatchScore(student, enterprise); enterprise.setMatchScore(score); // 把分?jǐn)?shù)塞回 Enterprise 對(duì)象 return enterprise; }) .sorted((e1, e2) - Double.compare(e2.getMatchScore(), e1.getMatchScore())) // 降序 .limit(10) // 只返回 Top10 .collect(Collectors.toList()); } private double calculateMatchScore(Student student, Enterprise enterprise) { double baseScore 0.0; // 1. 專業(yè)匹配字符串包含判斷避免精確相等導(dǎo)致漏匹配 if (enterprise.getRecruitMajors() ! null enterprise.getRecruitMajors().contains(student.getMajor())) { baseScore 30.0; } double skillScore 0.0; // 2. 技能證書匹配student.getCertificates() 返回逗號(hào)分隔字符串如 CET4,JavaCert String[] certs student.getCertificates().split(,); for (String cert : certs) { if (CET4.equals(cert.trim()) || JavaCert.equals(cert.trim())) { skillScore 10.0; } } double behaviorScore 0.0; // 3. 選修課匹配student.getElectives() 如 ERP,HRM String[] electives student.getElectives().split(,); for (String ele : electives) { if (ERP.equals(ele.trim()) || HRM.equals(ele.trim())) { behaviorScore 5.0; } } return baseScore * BASE_WEIGHT skillScore * SKILL_WEIGHT behaviorScore * BEHAVIOR_WEIGHT; } }參數(shù)說明BASE_WEIGHT等三個(gè)常量必須抽成Value(${recommend.weight.base})方便答辯時(shí)演示“調(diào)高行為權(quán)重后ERP 課學(xué)生更傾向推 ERP 公司”。enterprise.getRecruitMajors()存的是逗號(hào)分隔字符串如計(jì)算機(jī),軟件工程,信息管理不是 JSON 數(shù)組——畢業(yè)設(shè)計(jì)數(shù)據(jù)庫(kù)設(shè)計(jì)要?jiǎng)?wù)實(shí)別為了“規(guī)范”搞復(fù)雜序列化。limit(10)是硬編碼但符合真實(shí)場(chǎng)景學(xué)生不可能看 100 個(gè)推薦Top10 才是有效信息密度。3.2 數(shù)據(jù)庫(kù)表設(shè)計(jì)為什么enterprise表里要冗余recruit_majors字段很多同學(xué)想“規(guī)范化”把企業(yè)招聘專業(yè)拆成enterprise_major關(guān)聯(lián)表。但畢業(yè)設(shè)計(jì)里一次推薦要 JOIN 3 張表student, enterprise, enterprise_major查詢變慢、SQL 復(fù)雜、答辯時(shí)解釋成本高。真實(shí)做法是字段名類型說明idBIGINT PK企業(yè)IDnameVARCHAR(100)企業(yè)名稱recruit_majorsVARCHAR(500)存計(jì)算機(jī),軟件工程,信息管理用逗號(hào)分隔便于LIKE %計(jì)算機(jī)%或 Javasplit()match_scoreDECIMAL(5,2)臨時(shí)存儲(chǔ)匹配分前端直接取用避免每次計(jì)算注意recruit_majors字段長(zhǎng)度設(shè)為 500 是經(jīng)驗(yàn)值——最多支持 30 個(gè)專業(yè)名平均 15 字留足余量。設(shè)太小會(huì)截?cái)嘣O(shè)太大浪費(fèi)空間且影響索引效率。4. Vue 前端對(duì)接不是“套模板”而是讓 axios 請(qǐng)求精準(zhǔn)命中 SSM 接口Vue 部分最容易變成“靜態(tài)頁(yè)面假數(shù)據(jù)”。但畢業(yè)設(shè)計(jì)要求前后端真正聯(lián)通學(xué)生登錄后首頁(yè)顯示“為您匹配的 10 家企業(yè)”點(diǎn)擊企業(yè)卡片跳轉(zhuǎn)詳情頁(yè)詳情頁(yè)里有“發(fā)送意向”按鈕。這就要求 Vue 精準(zhǔn)理解 SSM 的 URL 路由、JSON 結(jié)構(gòu)、跨域處理。4.1 Axios 配置全局 baseURL 和請(qǐng)求攔截器是剛需main.js中必須統(tǒng)一 baseURL避免每個(gè)組件里寫http://localhost:8080/api/...// src/utils/request.js import axios from axios const request axios.create({ baseURL: http://localhost:8080, // SSM 后端部署在 Tomcat 根路徑 timeout: 10000 }) // 請(qǐng)求攔截自動(dòng)帶上 token畢業(yè)設(shè)計(jì)可簡(jiǎn)化為固定字符串 request.interceptors.request.use(config { config.headers.Authorization Bearer student_123 // 演示用實(shí)際可存 localStorage return config }) export default request然后在組件中直接調(diào)用script import request from /utils/request export default { data() { return { enterprises: [] } }, async mounted() { try { const res await request.get(/api/recommend/enterprises?studentId1) this.enterprises res.data // 注意SSM Controller 返回的是 {code:200, data: [...]} } catch (err) { console.error(獲取推薦企業(yè)失敗, err) } } } /script關(guān)鍵點(diǎn)SSM 的 Controller 必須返回標(biāo)準(zhǔn) JSON 包裹體不能直接return ListEnterprise。否則 Vue 收到的是數(shù)組但res.data會(huì)是undefined因?yàn)闆] data 字段。正確寫法ResponseBody GetMapping(/api/recommend/enterprises) public Result recommend(RequestParam Long studentId) { ListEnterprise list recommendService.recommendEnterprises(studentId); return Result.success(list); // Result 是自定義響應(yīng)類含 code/msg/data }4.2 Vue Router 路由守衛(wèi)學(xué)生未登錄時(shí)強(qiáng)制跳轉(zhuǎn)登錄頁(yè)畢業(yè)設(shè)計(jì)常忽略權(quán)限控制。學(xué)生直接輸入/dashboard應(yīng)該跳回/login。router/index.js中加router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.meta.requiresAuth !token) { next(/login) } else { next() } })并在路由定義中標(biāo)記{ path: /dashboard, name: Dashboard, component: () import(/views/Dashboard.vue), meta: { requiresAuth: true } // 這個(gè) meta 是守衛(wèi)判斷依據(jù) }玄學(xué)提示localStorage.getItem(token)在 Vue DevTools 里能看到答辯老師會(huì)檢查“你有沒有做登錄態(tài)校驗(yàn)”。哪怕 token 是寫死的student_123也比沒做強(qiáng)十倍。5. 避坑指南答辯前必查的 5 個(gè)致命細(xì)節(jié)附現(xiàn)象、原因、解法這些坑我?guī)н^ 17 屆畢設(shè)90% 的學(xué)生都踩過至少 2 個(gè)。不是代碼寫得不對(duì)而是環(huán)境、配置、認(rèn)知偏差導(dǎo)致的“看起來正常其實(shí)廢了”。5.1 現(xiàn)象Tomcat 啟動(dòng)成功但訪問http://localhost:8080顯示 404/api/xxx全掛原因web.xml中DispatcherServlet的url-pattern寫成了/*.do或/api/*導(dǎo)致靜態(tài)資源Vue 的index.html、js/app.js無法被 Tomcat 默認(rèn) Servlet 處理。解法url-pattern//url-pattern是唯一正解。再在springmvc-servlet.xml中加靜態(tài)資源放行mvc:default-servlet-handler/ !-- 讓 Tomcat 處理 /static/ /js/ /css/ -- mvc:resources mapping/static/** location/static/ /5.2 現(xiàn)象Vue 頁(yè)面能打開但推薦列表空白控制臺(tái)無報(bào)錯(cuò)Network 里請(qǐng)求狀態(tài)是(cancelled)原因Vue 開發(fā)服務(wù)器npm run serve默認(rèn)端口是 8080和 Tomcat 沖突。瀏覽器同時(shí)向localhost:8080發(fā)請(qǐng)求一半給 Vue一半給 Tomcat亂套。解法方案 A推薦Vue 改端口在vue.config.js中加devServer: { port: 8081 }然后axios baseURL改為http://localhost:8081→ 不這是錯(cuò)的方案 B正解Vue 不起 dev server直接npm run build生成dist目錄把dist里的所有文件復(fù)制到 Tomcat 的webapps/ROOT/下。這樣前后端同域徹底規(guī)避跨域。5.3 現(xiàn)象MySQL 插入中文亂碼學(xué)生姓名顯示為??原因不只是數(shù)據(jù)庫(kù)字符集設(shè)為utf8mb4就夠了JDBC URL 缺少useUnicodetruecharacterEncodingUTF-8serverTimezoneGMT%2B8參數(shù)。解法applicationContext.xml中dataSource的url必須長(zhǎng)這樣property nameurl valuejdbc:mysql://localhost:3306/student_recomm?useUnicodetrueamp;characterEncodingUTF-8amp;serverTimezoneGMT%2B8/注意要寫成amp;XML 語(yǔ)法要求。5.4 現(xiàn)象LW論文里寫了“采用協(xié)同過濾算法”但代碼里全是 if-else答辯被當(dāng)場(chǎng)質(zhì)疑原因?qū)W生照搬網(wǎng)上論文模板沒理解“協(xié)同過濾”需要用戶-物品交互矩陣如學(xué)生投遞記錄、企業(yè)查看記錄而本系統(tǒng)初始數(shù)據(jù)只有學(xué)生檔案和企業(yè)招聘要求根本沒有交互行為數(shù)據(jù)。解法立刻刪掉論文里所有“協(xié)同過濾”“矩陣分解”“隱語(yǔ)義模型”字眼替換為“基于規(guī)則的多維度加權(quán)匹配算法”。在“算法設(shè)計(jì)”章節(jié)畫一張清晰流程圖輸入學(xué)生檔案→ 處理三類評(píng)分→ 輸出匹配分排序。真實(shí)比炫技重要。5.5 現(xiàn)象PPT 里系統(tǒng)架構(gòu)圖畫了“Vue SpringCloud Redis Elasticsearch”但源碼里連 Redis 依賴都沒加原因套用網(wǎng)上高級(jí)架構(gòu)圖以為“畫得高大上項(xiàng)目水平高”。結(jié)果答辯時(shí)被問“Redis 緩存了什么數(shù)據(jù)緩存失效策略怎么設(shè)”瞬間啞火。解法架構(gòu)圖只畫你真實(shí)用到的技術(shù)。本系統(tǒng)就是Vue前端→ TomcatWeb 容器→ SpringMVC路由→ SpringIoC/事務(wù)→ MyBatisDAO→ MySQL數(shù)據(jù)庫(kù)。多畫一個(gè)框就要多準(zhǔn)備 3 個(gè)問題的答案。6. 答辯加分技巧用“可驗(yàn)證改動(dòng)”代替“功能描述”讓老師看見你的動(dòng)手痕跡答辯不是復(fù)述 PPT是證明你真的改過、調(diào)過、跑過。我?guī)W(xué)生時(shí)最后 3 天一定讓他們做三件事每件都能在 5 分鐘內(nèi)現(xiàn)場(chǎng)演示且老師能立刻驗(yàn)證6.1 技巧一準(zhǔn)備一個(gè)“開關(guān)式”配置項(xiàng)現(xiàn)場(chǎng)演示權(quán)重調(diào)整效果在application.properties里加一行# 推薦權(quán)重配置答辯時(shí)可現(xiàn)場(chǎng)改 recommend.weight.base0.5 recommend.weight.skill0.3 recommend.weight.behavior0.2然后RecommendServiceImpl中用Value注入Value(${recommend.weight.base}) private double baseWeight;答辯時(shí)打開application.properties把base0.5改成0.2重啟 Tomcat刷新頁(yè)面——Top10 企業(yè)順序立刻變化。老師看到“你真改了配置、真起了作用”信任感拉滿。比講十分鐘原理管用。6.2 技巧二數(shù)據(jù)庫(kù)里預(yù)埋兩組對(duì)比數(shù)據(jù)現(xiàn)場(chǎng)導(dǎo)出 Excel 證明匹配邏輯在 MySQL 里手動(dòng)插入兩條典型學(xué)生數(shù)據(jù)學(xué)生 A專業(yè)計(jì)算機(jī)證書CET4,JavaCert選修ERP→ 應(yīng)該匹配 ERP 公司學(xué)生 B專業(yè)工商管理證書CET6選修HRM→ 應(yīng)該匹配 HR 服務(wù)公司答辯時(shí)用 Navicat 連上數(shù)據(jù)庫(kù)執(zhí)行SELECT s.name, s.major, s.certificates, s.electives, e.name AS enterprise_name, e.recruit_majors, r.match_score FROM student s JOIN recommend_result r ON s.id r.student_id JOIN enterprise e ON r.enterprise_id e.id WHERE s.id IN (1, 2) ORDER BY r.match_score DESC;把結(jié)果導(dǎo)出 Excel現(xiàn)場(chǎng)打開指著表格說“看學(xué)生 A 的 ERP 匹配分比學(xué)生 B 高因?yàn)樾袨闄?quán)重生效了?!?—— 數(shù)據(jù)不會(huì)說謊這是最硬的證據(jù)。6.3 技巧三PPT 里放一張“真實(shí)請(qǐng)求鏈路截圖”而不是架構(gòu)圖刪掉所有“Vue SpringCloud MQ”那種假圖。換成一張你用 Chrome DevTools Network 面板截的真實(shí)圖左側(cè)GET http://localhost:8080/api/recommend/enterprises?studentId1中間Status200 OKSize2.3KB右側(cè)Response 面板里展開 JSON高亮data[0].name和data[0].matchScore這張圖說明三件事后端接口真實(shí)存在、返回結(jié)構(gòu)正確、前端能拿到數(shù)據(jù)。比畫一百?gòu)埣軜?gòu)圖都有力。我?guī)У淖詈笠粚脤W(xué)生有個(gè)姑娘答辯前夜發(fā)現(xiàn)mybatis-spring依賴漏了死活注入不了 Mapper。她沒重裝環(huán)境而是直接把mybatis-spring-1.3.2.jar手動(dòng)丟進(jìn) Tomcat 的lib目錄重啟搞定。答辯時(shí)老師問“你怎么解決的”她打開 Tomcatlib文件夾指著那個(gè) jar 包說“我把它‘焊’進(jìn)去了?!?全場(chǎng)笑老師點(diǎn)頭——工程師的尊嚴(yán)不在代碼多漂亮而在問題來了你手里有錘子也有膽子砸下去。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取