spring4+jersey2+hiberbate5+maven構(gòu)建restful項(xiàng)目

寫給自己記錄琳骡,順便留給需要的人

環(huán)境
  • myeclipse2014
  • jdk 1.8
  • tomcat 8.0.41
  • mysql 5.7.14
  • maven 3.3.9
  • spring 4.3.8.RELEASE
  • jersey 2.25.1
  • hibernate 5.2.10.Final
  • 接口測(cè)試工具:postman
用到的包:pom.xml
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>4.3.8.RELEASE</spring.version>
    <jersey.version>2.25.1</jersey.version>
</properties>
<dependencies>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>
    <!-- jersey-spring3-->
    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-spring3</artifactId>
        <version>${jersey.version}</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!-- jackson -->
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-all</artifactId>
        <version>1.9.11</version>
    </dependency>
    <!-- spring -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- c3p0 -->
    <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5.2</version>
    </dependency>
    <dependency> 
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.10</version>
    </dependency>
    <!-- hibernate -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.2.10.Final</version>
    </dependency>
    <!-- mysqlDriver -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>
</dependencies>
Spring配置: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"
    xmlns:p="http://www.springframework.org/schema/p"
    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/tx  
                          http://www.springframework.org/schema/tx/spring-tx.xsd  
                          http://www.springframework.org/schema/aop
                          http://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:annotation-config></context:annotation-config>
    <context:component-scan base-package="com.ourfor"></context:component-scan>

    <context:property-placeholder location="classpath:jdbc.properties" file-encoding="utf-8" ignore-unresolvable="true" />

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" 
        p:driverClass="${jdbc.driverClassName}"
        p:jdbcUrl="${jdbc.url}" 
        p:user="${jdbc.username}" 
        p:password="${jdbc.password}"
        p:testConnectionOnCheckout="${jdbc.c3p0.testConnectionOnCheckout}"
        p:testConnectionOnCheckin="${jdbc.c3p0.testConnectionOnCheckin}"
        p:idleConnectionTestPeriod="${jdbc.c3p0.idleConnectionTestPeriod}"
        p:initialPoolSize="${jdbc.c3p0.initialPoolSize}" 
        p:minPoolSize="${jdbc.c3p0.minPoolSize}"
        p:maxPoolSize="${jdbc.c3p0.maxPoolSize}"
        p:maxIdleTime="${jdbc.c3p0.maxIdleTime}" />

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan">
            <list>
                <!-- 可以加多個(gè)包 -->
                <value>com.ourfor.*.bean</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
                <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
            </props>
        </property>
    </bean>

    <!-- 配置Hibernate事務(wù)管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- 配置事務(wù)異常封裝 -->
    <bean id="persistenceExceptionTranslationPostProcessor" class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

    <!-- 配合<tx:advice>和<aop:advisor>完成了事務(wù)切面的定義 -->
    <!-- 使用強(qiáng)大的切點(diǎn)表達(dá)式是語(yǔ)言輕松定義目標(biāo)方法 -->
    <aop:config proxy-target-class="true">
        <!-- 通過(guò)aop定義事務(wù)增強(qiáng)切面 -->
        <aop:pointcut expression=" execution(* com.ourfor..*(..))"
            id="serviceMethod" />
        <!-- 引用事務(wù)增強(qiáng) -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
    </aop:config>
    <!-- 事務(wù)增強(qiáng) -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!-- 事務(wù)屬性定義 -->
        <tx:attributes>
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>
</beans>

需要注意按自己項(xiàng)目修改的地方:
Spring要掃描的包

<context:component-scan base-package="包名"></context:component-scan>

Spring 注解 hibernate 實(shí)體bean的包

<property name="packagesToScan">
    <list>
        <value>包名.*.bean</value>
    </list>
</property>

Spring事務(wù)管理的包

  • execution(* 包名..*(..)):當(dāng)前包及子包下面的類
  • execution(* 包名.*(..)):當(dāng)前包下面的類
<aop:config proxy-target-class="true">
    <!-- 通過(guò)aop定義事務(wù)增強(qiáng)切面 -->
    <aop:pointcut expression=" execution(* 包名..*(..))"
        id="serviceMethod" />
    <!-- 引用事務(wù)增強(qiáng) -->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
</aop:config>
jdbc.properties
#-----------------------------------------------------
# 數(shù)據(jù)庫(kù)配置
#-----------------------------------------------------
host=127.0.0.1
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://${host}:3306/test
jdbc.username=root
jdbc.password=toor
#-----------------------------------------------------
#c3p0配置
#-----------------------------------------------------
jdbc.c3p0.testConnectionOnCheckout=false
jdbc.c3p0.testConnectionOnCheckin=true
jdbc.c3p0.idleConnectionTestPeriod=3600
jdbc.c3p0.initialPoolSize=10
jdbc.c3p0.minPoolSize=10
jdbc.c3p0.maxPoolSize=100
jdbc.c3p0.maxIdleTime=3600
#-----------------------------------------------------
# hibernate配置
#-----------------------------------------------------
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.hbm2ddl.auto=update
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>Demo</display-name>
    <module-name>Demo</module-name>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>Way REST Service</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.ourfor.rest.RestApplication</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Way REST Service</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>

jersey2 還需指定JAX-RS application

<init-param>
    <param-name>javax.ws.rs.Application</param-name>
    <param-value>com.ourfor.rest.RestApplication</param-value>
</init-param>
RestApplication.java
package com.ourfor.rest;

import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import org.glassfish.jersey.server.ResourceConfig;

public class RestApplication extends ResourceConfig {
    public RestApplication() {
        packages("com.ourfor");
        register(JacksonJsonProvider.class);
    }
}
User.bean
package com.ourfor.rest.bean;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "t_user")
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "userId", unique = true)
    private String userId;
    @Column(name = "userName")
    private String userName;
    @Column(name = "age")
    private String age;
    @Column(name = "t")
    private String t;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getT() {
        return t;
    }

    public void setT(String t) {
        this.t = t;
    }
}
UserDao.java
package com.ourfor.rest.dao;

import java.util.List;
import com.ourfor.rest.bean.User;
 
public interface UserDao {
    
    public User getUserById(String id);
    public boolean deleteUserById(String id);
    public boolean createUser(User user);
    public boolean updateUser(User user);
    public List<User> getAllUsers();

}

UserDaoImpl.java
package com.ourfor.rest.dao.impl;

import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.ourfor.rest.bean.User;
import com.ourfor.rest.dao.UserDao;

@Repository
public class UserDaoImpl implements UserDao {

    @Autowired
    private SessionFactory sessionFactory;

    private Session getSession() {
        return sessionFactory.openSession();
    }

    @Override
    public User getUserById(String id) {
        Session s = null;
        Transaction t = null;
        User user = null;
        try {
            s = getSession();
            t = s.beginTransaction();
            String hql = "from User where userId='" + id + "'";
            Query query = s.createQuery(hql);
            user = (User) query.uniqueResult();
            t.commit();
        } catch (Exception err) {
            t.rollback();
            err.printStackTrace();
        } finally {
            s.close();
        }
        return user;
    }

    @Override
    public boolean deleteUserById(String id) {
        Session s = null;
        Transaction t = null;
        boolean flag = false;
        try {
            s = getSession();
            t = s.beginTransaction();
            User user = new User();
            user.setUserId(id);
            s.delete(user);
            t.commit();
            flag = true;
        } catch (Exception err) {
            t.rollback();
            err.printStackTrace();
        } finally {
            s.close();
        }
        return flag;
    }

    @Override
    public boolean createUser(User user) {
        Session s = null;
        Transaction t = null;
        boolean flag = false;
        try {
            s = getSession();
            t = s.beginTransaction();
            s.save(user);
            t.commit();
            flag = true;
        } catch (Exception err) {
            t.rollback();
            err.printStackTrace();
        } finally {
            s.close();
        }
        return flag;
    }

    @Override
    public boolean updateUser(User user) {
        Session s = null;
        Transaction t = null;
        boolean flag = false;
        try {
            s = getSession();
            t = s.beginTransaction();
            s.update(user);
            t.commit();
            flag = true;
        } catch (Exception err) {
            t.rollback();
            err.printStackTrace();
        } finally {
            s.close();
        }
        return flag;
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<User> getAllUsers() {
        Session s = null;
        Transaction t = null;
        List<User> uesrs = null;
        try {
            s = getSession();
            t = s.beginTransaction();
            String hql = " from  User"; 
            Query query = s.createQuery(hql);
            uesrs = query.list();
            t.commit();
        } catch (Exception err) {
            t.rollback();
            err.printStackTrace();
        } finally {
            s.close();
        }
        return uesrs;
    }

}
UserService.java
package com.ourfor.rest.service;

import java.util.List;
import com.ourfor.rest.bean.User;
 
public interface UserService {

    public User getUserById(String id);
    public boolean deleteUserById(String id);
    public boolean createUser(User user);
    public boolean updateUser(User user);
    public List<User> getAllUsers();

}

UserServiceImpl.java
package com.ourfor.rest.service.impl;

import java.util.List;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ourfor.rest.bean.User;
import com.ourfor.rest.dao.UserDao;
import com.ourfor.rest.service.UserService;

@Service
public class UserServiceImpl implements UserService {
    
    @Resource
    @Autowired
    private UserDao userDao;
    
    public UserServiceImpl() {
        // TODO Auto-generated constructor stub
    }

    @Override
    public User getUserById(String id) {
        return userDao.getUserById(id);
    }

    @Override
    public boolean deleteUserById(String id) {
        return userDao.deleteUserById(id);
    }

    @Override
    public boolean createUser(User user) {
        return userDao.createUser(user);
    }

    @Override
    public boolean updateUser(User user) {
        return userDao.updateUser(user);
    }

    @Override
    public List<User> getAllUsers() {
        return userDao.getAllUsers();
    }

}

UserResource.java
package com.ourfor.rest.resources;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.springframework.beans.factory.annotation.Autowired;
import com.ourfor.rest.bean.User;
import com.ourfor.rest.service.impl.UserServiceImpl;

@Path("/users")
public class UserResource {
    private static final Logger LOGGER = Logger.getLogger(UserResource.class.getName());
    
    @Autowired
    private UserServiceImpl userServiceImpl;
    
    public UserResource() {
        LOGGER.fine("UserResource()");
    }
    
    /**
     * 增加
     * @param user
     */
    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Consumes({MediaType.APPLICATION_JSON})
    public String createUser(User user)
    {
        if(userServiceImpl.createUser(user)){
            return "{\"flag\":\"true\"}";
        }else{
            return "{\"flag\":\"false\"}";
        }
    }
    
    /**
     * 刪除
     * @param id
     */
    @DELETE
    @Produces({MediaType.APPLICATION_JSON})
    @Path("{id}")
    public String deleteUser(@PathParam("id")String id){
        
        if(userServiceImpl.deleteUserById(id)){
            return "{\"flag\":\"true\"}";
        }else{
            return "{\"flag\":\"false\"}";
        }
    }
    
    /**
     * 修改
     * @param user
     */
    @PUT
    @Produces({MediaType.APPLICATION_JSON})
    @Consumes({MediaType.APPLICATION_JSON})
    public String updateUser(User user){
        
        if(userServiceImpl.updateUser(user)){
            return "{\"flag\":\"true\"}";
        }else{
            return "{\"flag\":\"false\"}";
        }
    }
 
    /**
     * 根據(jù)id查詢
     * @param id
     * @return
     */
    @GET
    @Path("{id}")
    @Produces({MediaType.APPLICATION_JSON})
    public User getUserById(@PathParam("id") String id){
        User user = userServiceImpl.getUserById(id);
        return user;
    }
   
    /**
     * 查詢所有
     * @return
     */
    @GET
    @Produces({MediaType.APPLICATION_JSON})
    public List<User> getAllUsers(){     
        List<User> users = new ArrayList<User>();   
        users = userServiceImpl.getAllUsers();
        return users;
    }
    
    
}
運(yùn)行測(cè)試
  • getAllUsers
image.png
  • createUser
image.png
  • getUserById
image.png
  • updateUser
image.png
  • deleteUser
image.png

至此,初始項(xiàng)目搭建完成

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末轧邪,一起剝皮案震驚了整個(gè)濱河市刽脖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌忌愚,老刑警劉巖曲管,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異硕糊,居然都是意外死亡院水,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門简十,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)檬某,“玉大人,你說(shuō)我怎么就攤上這事螟蝙』帜眨” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵胰默,是天一觀的道長(zhǎng)场斑。 經(jīng)常有香客問(wèn)我,道長(zhǎng)初坠,這世上最難降的妖魔是什么和簸? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮碟刺,結(jié)果婚禮上锁保,老公的妹妹穿的比我還像新娘。我一直安慰自己半沽,他們只是感情好爽柒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著者填,像睡著了一般浩村。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上占哟,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天心墅,我揣著相機(jī)與錄音酿矢,去河邊找鬼。 笑死怎燥,一個(gè)胖子當(dāng)著我的面吹牛瘫筐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播铐姚,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼策肝,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了隐绵?” 一聲冷哼從身側(cè)響起之众,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤依许,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后帘睦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體袍患,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡诡延,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年滞欠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片筛璧。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖朗儒,靈堂內(nèi)的尸體忽然破棺而出参淹,到底是詐尸還是另有隱情浙值,我是刑警寧澤开呐,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站颓哮,受9級(jí)特大地震影響冕茅,放射性物質(zhì)發(fā)生泄漏姨伤。R本人自食惡果不足惜乍楚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一徒溪、第九天 我趴在偏房一處隱蔽的房頂上張望臊泌。 院中可真熱鬧渠概,春花似錦播揪、人聲如沸筒狠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)峡继。三九已至碾牌,卻和暖如春舶吗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背检激。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饺律,地道東北人复濒。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓巧颈,卻偏偏與公主長(zhǎng)得像洛二,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子娶吞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容