成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Java后端支付大雜燴之core.dao,service,web(重點(diǎn)是接口的設(shè)計(jì))(二)

sourcenode / 2926人閱讀

摘要:是一個(gè)使用語(yǔ)言集成三方支付的小,現(xiàn)已集成支付寶國(guó)內(nèi)國(guó)際移動(dòng)端端微信銀聯(lián)光大網(wǎng)關(guān)網(wǎng)頁(yè)郵政支付,采用的技術(shù)棧為。系統(tǒng)初始化監(jiān)聽(tīng)器在系統(tǒng)啟動(dòng)時(shí)運(yùn)行進(jìn)行一些初始化工作加載銀聯(lián)配置文件緩存初始化忽略過(guò)濾器我們先看關(guān)于日志的,真心看不懂,后面有一大堆。

PayMap

PayMap是一個(gè)使用Java語(yǔ)言集成三方支付的小Demo,現(xiàn)已集成支付寶(國(guó)內(nèi)、國(guó)際、移動(dòng)端、PC端)、微信、銀聯(lián)(ACP、UPOP)、光大(網(wǎng)關(guān)、網(wǎng)頁(yè))、郵政支付,采用的技術(shù)棧為:SpringMVC+Spring+MyBatis+Shiro+RabbitMQ+Redis。

特性

支持前面提到的各種**支付

支付請(qǐng)求調(diào)用支持HTTP和異步MQ

控制層統(tǒng)一異常處理

LogBack日志記錄

Redis緩存機(jī)制

Shiro安全機(jī)制

MyBatis代碼自動(dòng)生成

HTTP請(qǐng)求日志記錄

RESTful APIs

說(shuō)明

1、本文項(xiàng)目來(lái)自Martin404,自己只是臨摹大佬的項(xiàng)目。

2、重要的是學(xué)習(xí)過(guò)程,而不是結(jié)果。但,結(jié)果同樣重要,加油。gogogo。

3、框架搭建就略過(guò)了。配置文件太多。遇到的時(shí)候貼出來(lái)。也收藏起來(lái),留著備用。

4、Gist、Insight.io for GitHub必備吧,劃詞翻譯不懂的單詞劃一劃。

5、在IDEA中我會(huì)注重代碼規(guī)范,但是這里為了節(jié)約地方,能省的就省略了。還請(qǐng)諒解。

6、代碼提交到這里了GitHub。根據(jù)提交記錄找自己想要的類(lèi)庫(kù)。

7、重要的在后面,一切都只只是剛剛開(kāi)始(希望不要被屏蔽)??!gogogo

2、核心包~common.dao,service,web,mq.

(1)、我們先從dao開(kāi)始吧,這里也可以是web。熟悉的來(lái)了,IBaseMapper 還是定義基礎(chǔ)接口,但與中不同的是這個(gè)用泛型修飾,為什么呢?先看一張圖。

圖片+代碼可以說(shuō)明一切問(wèn)題。反射+泛型。很重。要是還不懂,再用文字描述

1、泛型類(lèi),是在實(shí)例化類(lèi)的時(shí)候指明泛型的具體類(lèi)型;支持創(chuàng)建可以按類(lèi)型進(jìn)行參數(shù)化的類(lèi)

2、泛型方法,是在調(diào)用方法的時(shí)候指明具體的類(lèi)型。public List findAll() {}

3、泛型接口,JDK,Spring中大量運(yùn)用泛型。

總結(jié)來(lái)說(shuō)泛型可以提高Java程序的類(lèi)型安全,所有的類(lèi)型轉(zhuǎn)換都是自動(dòng)和隱式的。為優(yōu)化,性能帶來(lái)收益。

IBaseDao接口:

/**
 * 持久層通用接口
 */
public interface IBaseDao {
   void save(T entity);
     void delete(T entity);
     void update(T entity);
     T findById(Serializable id);
     List findAll();
}

BaseDaoImpl實(shí)現(xiàn)類(lèi):

/**
 * 持久層通用實(shí)現(xiàn)
 */
public class BaseDaoImpl extends HibernateDaoSupport implements IBaseDao {
    //代表的是某個(gè)實(shí)體的類(lèi)型
    private Class entityClass;

    @Resource//根據(jù)類(lèi)型注入spring工廠中的會(huì)話工廠對(duì)象sessionFactory
    public void setMySessionFactory(SessionFactory sessionFactory){
        super.setSessionFactory(sessionFactory);
    }

    //在父類(lèi)(BaseDaoImpl)的構(gòu)造方法中動(dòng)態(tài)獲得entityClass
    public BaseDaoImpl() {
        ParameterizedType superclass = (ParameterizedType) this.getClass().getGenericSuperclass();
        //獲得父類(lèi)上聲明的泛型數(shù)組
        Type[] actualTypeArguments = superclass.getActualTypeArguments();
        entityClass = (Class) actualTypeArguments[0];
    }
    public void save(T entity) {
        this.getHibernateTemplate().save(entity);
    }

    public T findById(Serializable id) {
        return this.getHibernateTemplate().get(entityClass, id);
    }

    public List findAll() {
        String hql = "FROM " + entityClass.getSimpleName();
        return (List) this.getHibernateTemplate().find(hql);
    }
}

(2)、接下來(lái),再看本項(xiàng)目中定義IBaseMapper

@SelectProvider注解用于生成查詢(xún)用的sql語(yǔ)句,有別于@Select注解,@SelectProvide指定一個(gè)Class及其方法,并且通過(guò)調(diào)用Class上的這個(gè)方法來(lái)獲得sql語(yǔ)句。

@ResultMap注解用于從查詢(xún)結(jié)果集RecordSet中取數(shù)據(jù)然后拼裝實(shí)體bean。

@SelectProvide方法,如果參數(shù)使用了@Param注解,那么參數(shù)在Map中以@Param的值為key

在這里使用了注解的形式,但是也可以在XMl方法配置。

public interface IBaseMapper {
    @SelectProvider(type = MapperProvider.class, method = "dynamicSQL")
    T selectOne(T record);
    @SelectProvider(type = MapperProvider.class, method = "dynamicSQL")
    T selectByPrimaryKey(Object key);

    @InsertProvider(type = MapperProvider.class, method = "dynamicSQL")
    int insert(T record);
    ...........................忽略了幾個(gè).......................
    @DeleteProvider(type = MapperProvider.class, method = "dynamicSQL")
    int delete(T record);
    @DeleteProvider(type = MapperProvider.class, method = "dynamicSQL")
    int deleteByPrimaryKey(Object key);
    @DeleteProvider(type = MapperProvider.class, method = "dynamicSQL")
    int deleteByExample(Object example);
    @UpdateProvider(type = MapperProvider.class, method = "dynamicSQL")
    int updateByExample(@Param("record") T record, @Param("example") Object example);

    List getAllByPage(RowBounds rowBounds);       //這個(gè)是用于分頁(yè)的。

}

(3)、中間插一個(gè)RabbitMQ MSG序列化JSON轉(zhuǎn)換器,主要作用是客戶端和服務(wù)端需要傳輸Json格式的數(shù)據(jù)包,所以需要進(jìn)行轉(zhuǎn)換。這個(gè)工具包也是必備的之一。友情提示,安裝MQ時(shí),一定要以系統(tǒng)管理員運(yùn)行CMD。

RabbitMQ已經(jīng)實(shí)現(xiàn)了Jackson的消息轉(zhuǎn)換(Jackson2JsonMessageConverter),由于考慮到效率,如下使用Gson實(shí)現(xiàn)消息轉(zhuǎn)換。

如下消息的轉(zhuǎn)換類(lèi)的接口MessageConverter,Jackson2JsonMessageConverter的父類(lèi)AbstractJsonMessageConverter針對(duì)json轉(zhuǎn)換的基類(lèi)。

我們實(shí)現(xiàn)Gson2JsonMessageConverter轉(zhuǎn)換類(lèi)也繼承AbstractJsonMessageConverter。

為了節(jié)約地方,代碼放Gist了,需要的時(shí)候直接去找。

/**
 * MQ MSG序列化JSON轉(zhuǎn)換器
 */
public class Gson2JsonMessageConverter extends AbstractJsonMessageConverter {

    private static Logger logger = LoggerFactory.getLogger(Gson2JsonMessageConverter.class);
    private static ClassMapper classMapper = new DefaultClassMapper();
    private static Gson gson = new Gson();

    @Override
    protected Message createMessage(Object object, MessageProperties messageProperties) {
        byte[] bytes = null;
        try {
            String jsonString = gson.toJson(object);
            jsonString.getBytes(getDefaultCharset());
        }
        catch (IOException e) {
            new MessageConversionException("Failed to convert Mesage context",e);
        }
        messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
        messageProperties.setContentEncoding(getDefaultCharset());
        if (bytes != null) {
            messageProperties.setContentLength(bytes.length);
        }
        classMapper.fromClass(object.getClass(),messageProperties);
        return new Message(bytes,messageProperties);
    }
    @Override
    public ClassMapper getClassMapper() {
        return new DefaultClassMapper();
    }
}

(4)、接下來(lái)就是定義基礎(chǔ)IBaseService以及實(shí)現(xiàn)類(lèi)

public interface IBaseService {
  /**
   * 根據(jù)主鍵查詢(xún)指定實(shí)體
   */
    T getId(Object id) ;
    List getByEntiry(T entity);
    PageInfo getByPage(RowBounds rowBounds);
    int save(T entity);
    int update(T entity);
    int delete(Object id);
    int saveSelective(T entity) throws DBException;
    int updateSelective(T entity);
}

IBaseService:全部代碼在這Gist

/**
 * Created by guo on 3/2/2018.
 */
public abstract class BaseService implements IBaseService {
    private static Logger logger = LoggerFactory.getLogger(BaseService.class);
    @Resource
    protected RabbitTemplate amqpTemplate;
    @Autowired
    protected RedisTemplate redisTemplate;

    public abstract IBaseMapper getBaseMapper();

    /**
     * 根據(jù)主鍵查詢(xún)指定實(shí)體
     * @param id
     * @return
     */
    @Override
    public T getId(Object id) {
        return this.getBaseMapper().selectByPrimaryKey(id);
    }
    /**
     * 獲取分頁(yè)數(shù)據(jù)
     */
    @Override
    public PageInfo getByPage(RowBounds rowBounds) {
        List list = this.getBaseMapper().getAllByPage(rowBounds);
        return new PageInfo(list);
    }
    /**
     * 保存對(duì)象,保存所有屬性
     */
    @Override
    public int save(T entity) {
        return this.getBaseMapper().insert(entity);
    }
    /**
     * 刪除指定數(shù)據(jù)
     */
    @Override
    public int delete(Object id) {
        return this.getBaseMapper().deleteByPrimaryKey(id);
    }
    /**
     * 更新對(duì)象,值更新對(duì)象中不為Null的屬性,主鍵不能為NULL
     */
    @Override
    public int updateSelective(T entity) {
        return this.getBaseMapper().updateByPrimaryKeySelective(entity);
    }
}

(5)、接下來(lái)就是web包中的內(nèi)容,涉及監(jiān)聽(tīng)器和過(guò)濾器。

/**
 * 系統(tǒng)初始化監(jiān)聽(tīng)器,在系統(tǒng)啟動(dòng)時(shí)運(yùn)行,進(jìn)行一些初始化工作
 */
public class InitListener implements javax.servlet.ServletContextListener {

    private static Logger logger = LoggerFactory.getLogger(InitListener.class);
    public static ApplicationContext context;

    public void contextDestroyed(ServletContextEvent arg0) {
    }

    public void contextInitialized(ServletContextEvent servletContextEvent) {
        context = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContextEvent.getServletContext());
        //加載銀聯(lián)upop配置文件
        SDKConfig.getConfig().loadPropertiesFromSrc();
        String proPath = servletContextEvent.getServletContext().getRealPath("/");
        SDKConfig config = SDKConfig.getConfig();
        config.setSignCertDir(proPath + config.getSignCertDir());
        config.setSignCertPath(proPath + config.getSignCertPath());
        config.setValidateCertDir(proPath + config.getValidateCertDir());
        //緩存初始化忽略
    }
}

過(guò)濾器:

我們先看關(guān)于日志的,真心看不懂,后面有一大堆。代碼地址

/**
 * request response log記錄過(guò)濾器
 */
public class LoggingFilter extends OncePerRequestFilter {

    protected static final Logger logger = LoggerFactory.getLogger(LoggingFilter.class);
    private static final String REQUEST_PREFIX = "Request: ";
    private static final String RESPONSE_PREFIX = "Response: ";
    private AtomicLong id = new AtomicLong(1);

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, final FilterChain filterChain) throws ServletException, IOException {
        if (logger.isDebugEnabled()) {
            long requestId = id.incrementAndGet();
            request = new RequestWrapper(requestId, request);
        }
        try {
            filterChain.doFilter(request, response);
        } finally {
            if (logger.isDebugEnabled()) {
                logRequest(request);
            }
        }
    }
    //...
}

還有一個(gè)請(qǐng)求包裝類(lèi),和響應(yīng)類(lèi)。。代碼地址

public class RequestWrapper extends HttpServletRequestWrapper {
    private final ByteArrayOutputStream bos = new ByteArrayOutputStream();
    private long id;

    public RequestWrapper(Long requestId, HttpServletRequest request) {
        super(request);
        this.id = requestId;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        return new ServletInputStream() {
            private TeeInputStream tee = new TeeInputStream(RequestWrapper.super.getInputStream(), bos);

            @Override
            public int read() throws IOException {
                return tee.read();
            }
        };
    }

    public byte[] toByteArray() {
        return bos.toByteArray();
    }
}

---------------------------------------------------------------------------------
public class ResponseWrapper extends HttpServletResponseWrapper {

    private final ByteArrayOutputStream bos = new ByteArrayOutputStream();
    private PrintWriter writer = new PrintWriter(bos);
    private long id;

    public ResponseWrapper(Long requestId, HttpServletResponse response) {
        super(response);
        this.id = requestId;
    }
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return new ServletOutputStream() {
            private TeeOutputStream tee = new TeeOutputStream(ResponseWrapper.super.getOutputStream(), bos);

            @Override
            public void write(int b) throws IOException {
                tee.write(b);
            }
        };
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        return new TeePrintWriter(super.getWriter(), writer);
    }

    public byte[] toByteArray() {
        return bos.toByteArray();
    }
}

這一塊只是得補(bǔ)補(bǔ),用到的時(shí)候再看,還有一個(gè)TeePrintWriter

核心包的東東算是完了,重點(diǎn)是在IBaseMapper、IBaseService的設(shè)計(jì)。這里用到了泛型,還有Mybatis3.X新特性,基于注解的。其實(shí)完全可以用XML配置文件。

gogogo 正式進(jìn)入業(yè)務(wù)邏輯部分。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/68640.html

相關(guān)文章

  • Java后端支付雜燴sps.controller(支付請(qǐng)求入口,配置文件)(五)

    摘要:重要的是學(xué)習(xí)過(guò)程,而不是結(jié)果。但,結(jié)果同樣重要,加油。。在這提一點(diǎn),由于網(wǎng)絡(luò)原因等異常情況支付平臺(tái)可能出現(xiàn)多次發(fā)送支付結(jié)果的情況,通知回調(diào)接口商戶要注意做好接口冪等,其余的不再多說(shuō)。 7、sps.controller.base,front. 說(shuō)明 如果有幸能看到,其實(shí)只為自己記錄,回頭復(fù)習(xí)用 1、本文項(xiàng)目來(lái)自Martin404,自己只是臨摹大佬的項(xiàng)目。 2、重要的是學(xué)習(xí)過(guò)程,而不是結(jié)...

    Joyven 評(píng)論0 收藏0
  • Java后端支付雜燴core.common、utils(異常,ID,日期,字符串等工具類(lèi))(一)

    摘要:但,結(jié)果同樣重要,加油。。而且可明確提出錯(cuò)誤信息。業(yè)務(wù)異常的自定義封裝類(lèi)實(shí)現(xiàn)和一樣,為了空間就不展示了。數(shù)據(jù)庫(kù)異常在看兩個(gè)類(lèi),驗(yàn)證信息異常。那就是字符串工具類(lèi)。字符串處理及轉(zhuǎn)換工具類(lèi),。 PayMap PayMap是一個(gè)使用Java語(yǔ)言集成三方支付的小Demo,現(xiàn)已集成支付寶(國(guó)內(nèi)、國(guó)際、移動(dòng)端、PC端)、微信、銀聯(lián)(ACP、UPOP)、光大(網(wǎng)關(guān)、網(wǎng)頁(yè))、郵政支付,采用的技術(shù)棧為:S...

    huayeluoliuhen 評(píng)論0 收藏0
  • Java 類(lèi)文章 - 收藏集 - 掘金

    摘要:而調(diào)用后端服務(wù)就應(yīng)用了的高級(jí)特分布式配置管理平臺(tái)后端掘金輕量的分布式配置管理平臺(tái)。關(guān)于網(wǎng)絡(luò)深度解讀后端掘金什么是網(wǎng)絡(luò)呢總的來(lái)說(shuō),網(wǎng)絡(luò)中的容器們可以相互通信,網(wǎng)絡(luò)外的又訪問(wèn)不了這些容器。 在 Java 路上,我看過(guò)的一些書(shū)、源碼和框架(持續(xù)更新) - 后端 - 掘金簡(jiǎn)書(shū) 占小狼轉(zhuǎn)載請(qǐng)注明原創(chuàng)出處,謝謝!如果讀完覺(jué)得有收獲的話,歡迎點(diǎn)贊加關(guān)注 物有本末,事有終始,知所先后,則近道矣 ......

    RayKr 評(píng)論0 收藏0
  • 從應(yīng)用到平臺(tái) - 云服務(wù)架構(gòu)演進(jìn)過(guò)程

    摘要:應(yīng)用的研發(fā)上線運(yùn)維運(yùn)營(yíng)形成閉環(huán),順利完成從對(duì)內(nèi)服務(wù)到公共平臺(tái)的升級(jí)。從功能角度,只能支持靜態(tài)方式設(shè)置反向代理,然后,而平臺(tái)有服務(wù)對(duì)應(yīng)的后端服務(wù)和端口是有動(dòng)態(tài)調(diào)整需求。架構(gòu)上是基礎(chǔ)組件需要進(jìn)行升級(jí),數(shù)據(jù)訪問(wèn)層日志監(jiān)控系統(tǒng)等。 介紹 ? ? ? ?MaxLeap早期是一家研發(fā)、運(yùn)營(yíng)移動(dòng)應(yīng)用和手機(jī)游戲公司,發(fā)展過(guò)程中積累了很多通用組件。這些組件很大程度幫公司在移動(dòng)研發(fā)過(guò)程中節(jié)省了時(shí)間和成本,...

    LiangJ 評(píng)論0 收藏0
  • 小程序上云,有點(diǎn)猛

    摘要:另外小程序云應(yīng)用有一套高可用架構(gòu),提供監(jiān)控預(yù)警能力。自主可控小程序云應(yīng)用提供服務(wù)器,開(kāi)發(fā)者可以擁有登錄或重啟,也可以修改密碼。也就是說(shuō),服務(wù)器是由小程序云應(yīng)用提供,但使用權(quán)歸開(kāi)發(fā)者。  前不久有一個(gè)朋友問(wèn)我,到底是做什么端的小程序比較好?   我只問(wèn)了一句,你的產(chǎn)品里是否涉及錢(qián)和服務(wù),如果涉及這兩者,建議你選擇支付寶小程序。你可以通過(guò)其他小程序玩裂變,但如果你想做服務(wù)和商業(yè),一定要考慮支付寶...

    jsdt 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<