利用全註解實現ssh的一個完整例子
在一個稍大的專案中,通常會有上百個元件,如果這些元件採用xml的bean定義來配置,顯然會增加配置檔案的體積,查詢以及維護起來也不太方便。個人也不喜歡配置那麼多的xml檔案。下面我們就利用java的註解實現ssh框架,註解相當於一種標記加了註解就等於打上了某種標記,沒加,則等於沒有某種標記,以後,javac編譯器,開發工具包和其他程式可以用反射來了解你的類以及各種元素上有何種標記,看你有什麼標記,就去幹相應的事,標記可以載入包,類,欄位,方法,方法的引數以及區域性變數上。關於註解在這裡不多說,網上大把資料。
先看看完整的工程目錄吧
1.為了使用註解我們需要配置web.xml檔案,在web-inf目錄下內容如下
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 載入spring配置檔案 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:applicationContext*.xml </param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!-- struts2 的配置 --> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> <init-param> <!-- //固定格式--> <param-name>actionPackages</param-name> <param-value>com.ssh</param-value> </init-param> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <display-name></display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
2.接下來看看spring和hibernate的配置檔案applicationContext.xml
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 使用 annotation --> <context:annotation-config /> <!-- 使用 annotation 自動註冊bean,並檢查@Controller, @Service, @Repository註解已被注入 --> <context:component-scan base-package="com.ssh" /> <!-- 資料庫配置 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"> </property> <property name="url" value="jdbc:mysql://localhost:3306/myssh"> </property> <property name="username" value="anan"></property> <property name="password" value="123456"></property> </bean> <!-- sessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.MySQLDialect </prop> <prop key="hibernate.show_sql">true</prop> <!-- 可以自動建立資料庫表(create),不建立(none) --> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> <!-- 包掃描的方式載入註解類(推薦) --> <property name="packagesToScan"> <list> <value>com.ssh.*</value> </list> </property> </bean> <!--JDBC事務管理器,根據你的情況使用不同的事務管理器,如果工程中有Hibernate,就用Hibernate的事務管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref local="dataSource" /> </property> </bean> <!-- 用註解來實現事務管理 --> <tx:annotation-driven transaction-manager="transactionManager" /> </beans>
基本都有註釋了,這裡不多說了,需要注意的是如果是自己搞回去用千萬記得要改上面的資料庫配置。
3.接下來我們再看看struts的配置檔案struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<!-- 開啟使用開發模式,詳細錯誤提示 -->
<constant name="struts.devMode" value="false" />
<!-- 將物件交給spring管理 -->
<constant name="struts.objectFactory" value="spring" />
<!-- 指定資源編碼型別 -->
<constant name="struts.i18n.encoding" value="UTF-8" />
<!-- 指定每次請求到達,重新載入資原始檔 -->
<constant name="struts.i18n.reload" value="false" />
<!-- 指定每次配置檔案更改後,自動重新載入 -->
<constant name="struts.configuration.xml.reload" value="false" />
<!-- 預設字尾名 -->
<!-- <constant name="struts.action.extension" value="do,action,jhtml,," /> -->
<!-- Struts Annotation -->
<!-- <constant name="actionPackages" value="com.test1"/> -->
</struts>
基本上註釋寫的很詳細了吧,我也不是很懂就那樣配置著先....
接下來我們就可以安心的寫java程式碼了,先建立如下圖所示的包和類
先看看實體類User.java
package com.ssh.user.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* 類名稱:User
* 類描述:使用者資訊實體
* 建立人:anan
* 建立時間:2012-12-21 下午10:55:19
* 修改人:anan
* 修改時間:2012-12-21 下午10:55:19
* 修改備註:
* @version
* */
@Entity
@Table(name = "user")
public class User {
/**
* 使用者id
*/
@Id
@Column(name = "userId")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int userId;
/**
* 使用者名稱
*/
@Column(name = "userName", length = 50)
private String userName;
/**
* 使用者登入密碼
*/
@Column(name = "passWord", length = 50)
private String passWord;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public User(int userId, String userName, String passWord) {
this.userId = userId;
this.userName = userName;
this.passWord = passWord;
}
public User(String userName, String passWord) {
this.userName = userName;
this.passWord = passWord;
}
public User(int userId) {
this.userId = userId;
}
public User() {
}
}
這是一個基本的pojo類,關鍵看看那幾個註解@Entity表示當前類是一個實體,@Table(name = "user")指定這個類對映到資料庫的哪一個表,@Column(name = "userId")表示這個屬性對映資料庫對應表中的那一列...
接下來看看UserDao.java
package com.ssh.user.dao;
import java.util.List;
import com.ssh.user.model.User;
/**
* 類名稱:UserDao
* 類描述:使用者控制dao實現資料庫操作介面
* 建立人:anan
* 建立時間:2012-12-21 下午11:05:46
* 修改人:anan
* 修改時間:2012-12-21 下午11:05:46
* 修改備註:
* @version
* */
public interface UserDao {
public void addUser(User user);
public void delUser(int userId);
public void updateUser(User user);
public List<User> selectUser();
public User getUserByUserId(int userId);
public boolean isExitByName(String userName);
public boolean isExitByNameAndPass(User user);
}
這是一個介面指定使用者操作,定義一些方法
接下來具體實現這些方法,看UserDaoImpl.java
package com.ssh.user.dao.impl;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.stereotype.Repository;
import com.ssh.user.dao.UserDao;
import com.ssh.user.model.User;
import com.ssh.util.MyHibernateDaoSupport;
/**
* 類名稱:UserDaoImpl
* 類描述:使用者控制dao實現資料庫操作介面實現
* 建立人:anan
* 建立時間:2012-12-21 下午11:07:43
* 修改人:anan
* 修改時間:2012-12-21 下午11:07:43
* 修改備註:
* @version
* */
@Repository("userDao")
public class UserDaoImpl extends MyHibernateDaoSupport implements UserDao{
public void addUser(User user) {
Session session = this.getSession(true);
Transaction tc = (Transaction) session.beginTransaction();
session.save(user);
try {
tc.commit();
} catch (Exception e) {
e.printStackTrace();
}
session.close();
}
public void delUser(int userId) {
Session session = this.getSession(true);
Transaction tc = (Transaction) session.beginTransaction();
User u = new User(userId);
session.delete(u);
try {
tc.commit();
} catch (Exception e) {
e.printStackTrace();
}
session.close();
}
public void updateUser(User user) {
Session session = this.getSession(true);
Transaction tc = (Transaction) session.beginTransaction();
session.update(user);
try {
tc.commit();
} catch (Exception e) {
e.printStackTrace();
}
session.close();
}
public List<User> selectUser() {
List<User> users = new ArrayList<User>();
Session session = this.getSession(true);
Transaction tc = (Transaction) session.beginTransaction();
List list = session.createQuery("From User").list();
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
User u = (User) iterator.next();
users.add(u);
}
try {
tc.commit();
} catch (Exception e) {
e.printStackTrace();
}
session.close();
return users;
}
public User getUserByUserId(int userId) {
Session session = this.getSession(true);
Transaction tc = (Transaction) session.beginTransaction();
//load 是說明資料庫中一定存在這條記錄,沒有則報出:ObjectNotFoundException
//get 如果查不到記錄,返回的是一個null
User user = (User)session.load(User.class, userId);
try {
tc.commit();
} catch (Exception e) {
e.printStackTrace();
}
session.close();
return user;
}
public boolean isExitByName(String userName) {
Session session = this.getSession(true);
Transaction tc = (Transaction) session.beginTransaction();
List user = (List)session.createQuery("From User u where u.userName=:userName").setString("userName", userName).list();
if(user.size()>0){
try {
tc.commit();
} catch (Exception e) {
e.printStackTrace();
}
session.close();
return true;
}
try {
tc.commit();
} catch (Exception e) {
e.printStackTrace();
}
session.close();
return false;
}
public boolean isExitByNameAndPass(User user) {
Session session = this.getSession(true);
Transaction tc = (Transaction) session.beginTransaction();
List users = (List)session.createQuery("From User u where u.userName=:userName and u.passWord=:passWord").setString("userName", user.getUserName()).setString("passWord", user.getPassWord()).list();
if(users.size()>0){
try {
tc.commit();
} catch (Exception e) {
e.printStackTrace();
}
session.close();
return true;
}
try {
tc.commit();
} catch (Exception e) {
e.printStackTrace();
}
session.close();
return false;
}
}
到這裡資料庫操作基本搞完,接下來寫業務邏輯程式碼,先看看UserService.java
package com.ssh.user.service;
import java.util.List;
import com.ssh.user.model.User;
/**
* 類名稱:UserService
* 類描述:使用者業務邏輯介面
* 建立人:anan
* 建立時間:2012-12-21 下午10:58:32
* 修改人:anan
* 修改時間:2012-12-21 下午10:58:32
* 修改備註:
* @version
* */
public interface UserService {
/**
* 判斷使用者是否存在
* @param userName
* @return user
* @
* */
public boolean isExitUser(String userName) ;
/**
* 判斷使用者是否存在
* @param userName passWord
* @return user
* @
* */
public boolean isExitByNameAndPass(User user) ;
/**
* 儲存使用者
* @param user
* @return boolean
* @
* */
public void save(User user) ;
/**
* 查詢所有使用者
* @param
* @return List<User>
* @
* */
public List<User> getUsers() ;
/**
* 刪除使用者
* @param userId
* @return
* @
* */
public void del(int userId) ;
/**
* 修改使用者
* @param user
* @return
* @
* */
public void update(User user) ;
/**
* 根據id獲得user
* @param userId
* @return user
* @
* */
public User getUserById(int userId) ;
}
這個只是一個介面,定義我們接下來需要的方法。下面是具體的實現類UserServiceImpl.java
package com.ssh.user.service.Impl;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.ssh.user.dao.UserDao;
import com.ssh.user.model.User;
import com.ssh.user.service.UserService;
/**
* 類名稱:UserServiceImpl
* 類描述:使用者資訊操作業務邏輯介面實現
* 建立人:anan
* 建立時間:2012-12-21 下午11:08:18
* 修改人:anan
* 修改時間:2012-12-21 下午11:08:18
* 修改備註:
* @version
* */
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserDao userDao;
public boolean isExitUser(String userName) {
return userDao.isExitByName(userName);
}
public void save(User user) {
userDao.addUser(user);
}
public List<User> getUsers() {
List<User> users = userDao.selectUser();
return users;
}
public void del(int userId) {
userDao.delUser(userId);
}
public void update(User user) {
userDao.updateUser(user);
}
public User getUserById(int userId) {
return userDao.getUserByUserId(userId);
}
public boolean isExitByNameAndPass(User user) {
return userDao.isExitByNameAndPass(user);
}
}
業務邏輯在這裡包括了判斷使用者是否存在,儲存使用者資訊,獲取使用者資訊,刪除使用者,更新使用者資訊等
通過上面兩個類業務邏輯層也就完成了,接下來寫檢視控制器,這裡只是寫了一個簡單的登入控制器LoginAction.java
package com.ssh.user.action;
import javax.annotation.Resource;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import com.opensymphony.xwork2.ActionSupport;
import com.ssh.user.dao.UserDao;
import com.ssh.user.model.User;
/**
* 類名稱:LoginAction
* 類描述:使用者控制器的實現
* 建立人:anan
* 建立時間:2012-12-21 下午11:17:36
* 修改人:anan
* 修改時間:2012-12-21 下午11:17:36
* 修改備註:
* @version
* */
@Action(value = "loginAction", results = {
@Result(name = "loginSuccess", location = "/loginSuss.jsp"),
@Result(name = "loginFailer", location = "/loginFailer.jsp") })
public class LoginAction extends ActionSupport {
private static final long serialVersionUID = -2266695172069461659L;
@Resource
private UserDao userDao;
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String login(){
boolean flag = userDao.isExitByNameAndPass(user);
if(flag){
return "loginSuccess";
}
return "loginFailer";
}
}
這個就是控制層。
再寫幾個jsp檔案來測試一下
內容如下:
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<s:form action="loginAction!login">
<s:textfield name="user.userName" label="userName"></s:textfield>
<s:textfield name="user.passWord" label="passWord"></s:textfield>
<s:submit value="login"></s:submit>
</s:form>
</body>
</html>
loginFailer.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'loginFailer.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
登入失敗 </body>
</html>
loginSuss.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'loginSuss.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
登入成功 <br>
</body>
</html>
啟動tomcat我們可以看到資料庫自動生成一個user表。我們新增一條記錄為下面測試
覺得使用了ssh結構之後整個工程的層次感就那樣出來了。搞鼓一下收穫還是蠻大的,基於註解的ssh是比xml方便很多,看大家喜歡吧
原始碼下地址
相關推薦
利用全註解實現ssh的一個完整例子
在一個稍大的專案中,通常會有上百個元件,如果這些元件採用xml的bean定義來配置,顯然會增加配置檔案的體積,查詢以及維護起來也不太方便。個人也不喜歡配置那麼多的xml檔案。下面我們就利用java的註解實現ssh框架,註解相當於一種標記加了註解就等於打上了某種標記,沒加,則
java用全註解實現ssh的一個完整例子
在一個稍大的專案中,通常會有上百個元件,如果這些元件採用xml的bean定義來配置,顯然會增加配置檔案的體積,查詢以及維護起來也不太方便。個人也不喜歡配置那麼多的xml檔案。下面我們就利用java的註解實現ssh框架,註解相當於一種標記加了註解就等於打上了某種標記,沒
用註解實現ssh的例子
在一個稍大的專案中,通常會有上百個元件,如果這些元件採用xml的bean定義來配置,顯然會增加配置檔案的體積,查詢以及維護起來也不太方便。個人也不喜歡配置那麼多的xml檔案。下面我們就利用java的註解實現ssh框架,註解相當於一種標記加了註解就等於打上了某種標記,沒
利用Ajax實現的一個DataGrid例子
利用Ajax的技術非同步呼叫伺服器端的Web Service,生成一個在客戶端分頁的DataGrid。 首先來看看我們的Web Servcie,它利用傳遞過來的SQL生成資料集,採用標準的DataGrid控制元件利用RenderControl輸出為標準的HTML。 name
Java反射+註解實現自動持久化小例子(程式碼未優化)
需要實現的功能:根據實體類自動生成Sql語句與引數。 基本思路是:在實體類上標識註解,使用反射讀取註解然後拼接Sql語句。 哦了,開始研究程式碼~ 有請主人公註解:
用java傳送lotus郵件一個完整例子
import lotus.domino.NotesException;import lotus.domino.Session;import lotus.domino.NotesFactory;import lotus.domino.Database;import lotus.
C語言利用switch語句實現輸入一個字母,輸出它前後緊挨著的字母
題目來源:大工慕課 連結 作者:Caleb Sung 題目要求 從螢幕上輸入一個字元,如果不是英文字母,輸出“這不是英文字母,請重新輸入”,然後重新輸入字元,如果是英文字母,以大寫字母的形式輸出字母表中它前面的字元和後面的字元,如果輸入的字元為‘a
利用Java程式碼實現把一個檔案從一個地方剪下到另一個地方
1、實現原理: 通過輸入流讀取檔案的內容,在通過輸出流把讀取到的內容輸出到其他檔案中,然後再讀取結束後刪除原來的檔案就完成了檔案的剪下。 1)首先在將要把檔案剪下到的地方建立一個同一個型別的檔案; 2)利用輸入流讀取原檔案的內容; 3)在讀取的過程中,把讀取到的內容通過輸出
[譯] 利用 Python中的 Bokeh 實現資料視覺化,第三部分:製作一個完整的儀表盤
原文地址:Data Visualization with Bokeh in Python, Part III: Making a Complete Dashboard 原文作者:Will Koehrsen 譯文出自:掘金翻譯計劃 本文永久連結:github.com/xitu/g
Tensorflow實現一個完整的CNN例子
使用了Tensorflow實現一個狗的類別的識別,模型中狗的類別一共為十種,資料集如下 使用到的工具包是tfleran,可以直接使用pip安裝 pip install tflearn 由於很多例子都是在mnist之類現有的資料集中跑的,當用到自己的資料集
C++中利用鏈表實現一個棧
pop sin 返回 void tac () node bool typedef 在實現棧之前應該思考棧的一些用法: push pop top isempty 想清楚棧頂的組成; 下面是實現代碼: 1 #include<iostream> 2 3 us
CSS 一個完整的例子
som rand comment one oge none dom ttl use My first web page What this is A simple page put together using HTML. I said a simple page
用socket.io實現websocket的一個簡單例子
soc .html www sock 在線 ket log html 簡單例子 http://biyeah.iteye.com/blog/1295196 socket.io的介紹 http://www.cnblogs.com/mazg/p/5467960.html
Python 利用socket 實現 ssh 跳轉
socket python squid 1.場景描述:主機A主機B主機C10.13.170.76172.28.117.156(squid)10.95.113.131 主機A---->主機B(80)--->主機C(22), A通過B的80訪問主機C131 2.Python代碼;im
一個C#操作RabbitMQ的完整例子
void 引用 rabbitmq sys fault 密碼 cnn nload subscribe 一、下載RabbitMQ http://www.rabbitmq.com/install-windows.html 二、下載OTP http://www.erlan
利用ssh-copy-id實現SSH無密碼登錄
ssh copy id 第一步: 產生公鑰與私鑰對:[[email protected]]# ssh-keygen -t rsa按照提示輸入完後,會在~/.ssh目錄下生成id_rsa和id_rsa.pub這兩個文件 第二步:用ssh-copy-id將公鑰復制到遠程機器中ssh-copy
一個完整的springmvc + ajaxfileupload實現圖片上傳的案例
multipart per cnblogs not his let facade func connector 一,原理 詳細原理請看這篇文章 springmvc + ajaxfileupload解決ajax不能異步上傳圖片的問題。java.lang.ClassCastEx
手把手教你實現一個完整的BST(超級詳細)
查找樹 str image isempty 使用 this 根據 數據 false 查找基本分類如下: 線性表的查找 順序查找 折半查找 分塊查找 樹表的查找 二叉排序樹 平衡二叉樹 B樹 B+樹 散列表的查找 今天介紹二叉排序樹。 二叉排序樹 ( Binary
關於註解繼承性的一個例子
span 收藏 UC string OS san blog throws java (轉載自: http://wzhw2008.iteye.com/blog/1723136) 子類可以繼承到父類上的註解嗎? ---------------------------------
用SSM框架實現第一個echarts的例子及一個調用百度開發者工具的例子
response char ons enc styles ping 地理編碼 nco swa 過年後的第一篇Blog,說實話年後的自己好慵懶,一直處於半睡半醒狀態 ̄□ ̄||。年後工作上用了好多新東西,像Spring Boot,Swagger,Jenkins,Maven,