简单的ssm+layui项目

简单的ssm+layui项目

1.项目介绍

1.项目的模块划分

项目处于对汽车4s维修店出发,总共有6个模块,其中包括维修工单管理、结算订单管理、还车管理、登录管理、汽车配件管理、系统管理,核心模块为维修工单管理与结算订单管理

2.项目的主要技术

项目后台框架采用 mybatis+spring+springmvc 前端使用的是layui
权限使用的是shiro框架 分页使用的是mybatis的插件pagehelper 对配件的查询使用了Lucene技术 登录实现了三方登录(维修登录) 对订单查询实现了cxf技术

2.项目搭建

GitHub地址:https://github.com/createMoreByMe/rpms.git
1.项目结构
采用分模块开发
项目总结构

2.basic-core 基本核心代码模块
basic-core主要放入我们总项目的基本父类
1.BaseMapper

package cn.xxx.basic.mapper;

import cn.xxx.basic.query.BaseQuery;
import com.github.pagehelper.Page;

import java.util.List;

/**
 * 基本的CRUD和分页查询的父类
 * @param <T>
 */
public interface BaseMapper<T> {
    void insert(T t);

    void deleteByPrimaryKey(Long id);

    void updateByPrimaryKey(T t);

    T selectByPrimaryKey(Long id);

    List<T> selectAll();

    /**根据分页条件得到查询结果
     * @param query
     * @return
     */
    Page<T> loadDataByQuery(BaseQuery query);
}

2.IBaseService
基本service的接口,定义我们需要的crud接口方法

package cn.xxx.basic.service;

import cn.xxx.basic.query.BaseQuery;
import cn.xxx.basic.utils.PageList;


import java.util.List;

public interface IBaseService<T> {

    void add(T t);

    void delete(Long id);

    void update(T t);

    T get(Long id);

    List<T> getAll();

    /**根据分页条件返回查询结果
     * @param query
     * @return
     */
    PageList<T> queryPage(BaseQuery query);
}

3.BaseServiceImpl
基本service的实现,这里的事物是通过后面Springaop的配置加入事务,并且采用钩子的思想,将子类联系在一起,子类不需要在配置事物

package cn.xxx.basic.service.impl;


import cn.xxx.basic.mapper.BaseMapper;
import cn.xxx.basic.query.BaseQuery;
import cn.xxx.basic.service.IBaseService;
import cn.xxx.basic.utils.PageList;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import java.util.List;


    public abstract class BaseServiceImpl<T> implements IBaseService<T> {

        //Basic没有引入spring相关包,不能使用注解注入,在具体service上实现本方法
        protected abstract BaseMapper<T> getMapper();

        @Override
    public void add(T t) {

        getMapper().insert(t);
       // int i=1/0;
    }

    @Override
    public void delete(Long id) {
        getMapper().deleteByPrimaryKey(id);
    }

    @Override
    public void update(T t) {
        getMapper().updateByPrimaryKey(t);
    }

    @Override
    public T get(Long id) {
        return getMapper().selectByPrimaryKey(id);
    }

    @Override
    public List<T> getAll() {
        return getMapper().selectAll();
    }

    /**
     * 返回的pageList对象 其中含有总条数 和总数据
     */
    @Override
    public PageList<T> queryPage(BaseQuery query) {
        Page<T> objects = PageHelper.startPage(query.getPage(), query.getLimit());
        //拿到分页后的总数据
        getMapper().loadDataByQuery(query);
        return new PageList<>(objects.getTotal(), objects.getResult());
    }
}

4.BasePage
基本分页功能,这里考虑到layui需要的分页数据,所以在字段提供 页数page和条数limit

package cn.xxx.basic.query;

//基本查询对象
public class BaseQuery {
    private Integer page=1;

    private Integer limit=10;

    public Integer getPage() {
        return page;
    }

    public void setPage(Integer page) {
        this.page = page;
    }

    public Integer getLimit() {
        return limit;
    }

    public void setLimit(Integer limit) {
        this.limit = limit;
    }
}

4.pom.xml
需要导入工具的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>carservice-total</artifactId>
        <groupId>cn.xxx.myteam</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>basic-core</artifactId>

    <dependencies>
        <!--导入基本工具模块-->
        <dependency>
            <artifactId>basic-utils</artifactId>
            <groupId>cn.xxx.myteam</groupId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.4</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.0.1</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>basic-core</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
                <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.7.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.20.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.2.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

3.rpms-common
项目的domain和query
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>carservice-total</artifactId>
        <groupId>cn.xxx.myteam</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>prms-mapper</artifactId>

    <properties>
        <generator.project.root>E:/soft/software/idea/workspace/carservice-total</generator.project.root>
    </properties>


    <dependencies>
        <dependency>
            <artifactId>rpms-common</artifactId>
            <groupId>cn.xxx.myteam</groupId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <artifactId>basic-core</artifactId>
            <groupId>cn.xxx.myteam</groupId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.3</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.20</version>
        </dependency>

        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.3</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.2.2</version>
        </dependency>

        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <!--代码生成器-->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.5</version>
        </dependency>


    </dependencies>

    <build>
        <finalName>crm-mapper</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.2</version>
                <configuration>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

4.rpms-mapper
项目的dao层,操作数据库

在这里插入代码片<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>carservice-total</artifactId>
        <groupId>cn.xxx.myteam</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>rpms-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>cn.xxx.myteam</groupId>
            <artifactId>prms-mapper</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>cn.xxx.myteam</groupId>
            <artifactId>rpms-common</artifactId>
            <version>${project.version}</version>
        </dependency>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-core</artifactId>
                <version>5.5.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-analyzers-common</artifactId>
                <version>5.5.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-queryparser</artifactId>
                <version>5.5.0</version>
            </dependency>
        <!-- shiro的支持包 -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-all</artifactId>
            <version>1.4.0</version>
            <type>pom</type>
        </dependency>
        <!-- shiro与Spring的集成包 -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>crm-service</finalName>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
            </plugins>

        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>


            </plugins>
        </pluginManagement>
    </build>
</project>```

5.rpms-service
主要写相关业务

<?xml version="1.0" encoding="UTF-8"?>



carservice-total
cn.xxx.myteam
1.0-SNAPSHOT

4.0.0

<artifactId>rpms-service</artifactId>

<dependencies>
    <dependency>
        <groupId>cn.xxx.myteam</groupId>
        <artifactId>prms-mapper</artifactId>
        <version>${project.version}</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>cn.xxx.myteam</groupId>
        <artifactId>rpms-common</artifactId>
        <version>${project.version}</version>
    </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>5.5.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-common</artifactId>
            <version>5.5.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>5.5.0</version>
        </dependency>
    <!-- shiro的支持包 -->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-all</artifactId>
        <version>1.4.0</version>
        <type>pom</type>
    </dependency>
    <!-- shiro与Spring的集成包 -->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.4.0</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>
</dependencies>

<build>
    <finalName>crm-service</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>

    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
        <plugins>


        </plugins>
    </pluginManagement>
</build>
```

6.rpms-controller
跳转页面 接受参数

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>carservice-total</artifactId>
        <groupId>cn.xxx.myteam</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>prms-web</artifactId>
    <dependencies>
        <dependency>
            <groupId>cn.xxx.myteam</groupId>
            <artifactId>rpms-service</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>cn.xxx.myteam</groupId>
            <artifactId>rpms-common</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.4</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <!-- json处理工具,springmvc4.2.4处理json依赖。注意jackson版本号,spring3和spring4不一样 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.6.5</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.6.5</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.6.5</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

        <!--<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.1</version>
        </dependency>-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>crm-web</finalName>

        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
            </plugin>
        </plugins>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->

            <plugins>

            </plugins>
        </pluginManagement>
    </build>

</project>

3.业务流程

1.主业务(维修主单 维修明细单 结算单的管理)
维修主单的填写:
业务流程:
接待员对进行维修的汽车进行信息的录入:如客户的姓名 地址 维修人员等,客户的姓名我们需要进行合法校验,但是不进行重名校验;地址我们可以对接百度地图的api,对地址录入进行规范和管理。
维修明细的填写:
业务流程:
接待员填写维修主单后,需要进行维修明细单的填写,填写主要的是相关汽修材料的价格、数量、及工时费,注意:当这个材料不足的时候,我们需要对接待人员提供提醒。
当我们对一个维修主单的修改时,我们需要对维修明细单来源于主单的信息如维修人员进行更新,主单和明细单存在组合关系
2.主业务(结算单的管理)
每一个录入单当维修明细的发生,都对应着一个结算单,结算单的状态表示付款的情况,我们可以将结算单进行付款方式的划分比如分期付款 全款付款,对付款的时间和付款的金额进行录入,方便对资金的把控,如果需要查询相关材料。
我们同时为客户提供了外部查询的功能,实现的方式为cxf,向客户返回相关的维修单信息,比如汽车维修情况、付款情况、相关维修人员信息,让客户更加放心
3.主业务(还车情况)
当结算单还款对应的结算要求的时候,会提醒还车人员进行对应车辆的送还,跟踪还车路线,还车情况,还车完毕后更新还车情况
4.其他业务
我们提供对权限管理,员工不同的权限进入不同的菜单,使用了shiro对登录进行拦截,
保证安全
系统服务:提供超级管理员对系统的菜单、权限、日志进行管理,其中日志使用了Springaop自定义注解进行对相关controller层的访问进行记录,保存。

4.相关技术点—Lucene

4.1全文搜索
含义:从全文数据进行检索,基于文本的检索
搜索方式:顺序扫描法
全文检索(对非结构化数据进行创建索引,提供搜索速度)
4.2.全文检索特点
速度快、对搜索的相关度进行排序(排名靠前的显示在前面)、对摘要进行截取、对关键字进行截取,高亮关键字,只关注文本不关注语义
4.3.全文检索的使用场景
替换模糊查询数据库,提高查询效率
搜索引擎的基础
全文检索应用框架 4.4.全文检索的流程
在这里插入图片描述核心:索引的创建,索引的搜索
索引的创建:通过分词器进行分词
索引的搜索:根据单词占语句的权重进行排序

4.5.lucene
lucence是一个用Java写的高性能、可伸缩的全文检索引擎工具包
相关jar

<dependencies>
    <dependency>
        <groupId>org.apache.lucene</groupId>
        <artifactId>lucene-core</artifactId>
        <version>5.5.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.lucene</groupId>
        <artifactId>lucene-analyzers-common</artifactId>
        <version>5.5.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.lucene</groupId>
        <artifactId>lucene-queryparser</artifactId>
        <version>5.5.0</version>
    </dependency>
</dependencies>

4.6简单应用
1.创建索引
将文本内容转换为document对象,在通过indexwriter将document对象添加到缓冲区并提交

//创建索引的数据 现在写死,以后根据实际应用场景
	String doc1 = "hello world";
	String doc2 = "hello java world";
	String doc3 = "hello lucene world";
	Private String path ="F:/eclipse/workspace/lucene/index/
hello";
@Test
	publicvoid testCreate() {
		try {
			//2、准备IndexWriter(索引写入器)
			//索引库的位置 FS fileSystem
			Directory d = FSDirectory.open(Paths.get(path ));
			//分词器
			Analyzer analyzer = new SimpleAnalyzer();
			//索引写入器的配置对象
			IndexWriterConfig conf = new IndexWriterConfig(analyzer);
			IndexWriter indexWriter = new IndexWriter(d, conf);
			System.out.println(indexWriter);
			
			//1、 把文本内容转换为Document对象
			//把文本转换为document对象
			Document document1 = new Document();
			//标题字段
			document1.add(new TextField("title", "doc1", Store.YES));
			document1.add(new TextField("content", doc1, Store.YES));
			//添加document到缓冲区
			indexWriter.addDocument(document1);
			Document document2 = new Document();
			//标题字段
			document2.add(new TextField("title", "doc2", Store.YES));
			document2.add(new TextField("content", doc2, Store.YES));
			//添加document到缓冲区
			indexWriter.addDocument(document2);
			Document document3 = new Document();
			//标题字段
			document3.add(new TextField("title", "doc3", Store.YES));
			document3.add(new TextField("content", doc3, Store.YES));
			
			//3 、通过IndexWriter,把Document添加到缓冲区并提交
			//添加document到缓冲区
			indexWriter.addDocument(document3);
			indexWriter.commit();
			indexWriter.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	
	}

2.搜索引擎
封装好需要查询的内容对象,使用indexsearcher获取查询到document对象,在转换为需要对象

@Test
	publicvoid testSearch() {
		String keyWord = "lucene";
		try {
			// * 1 封装查询提交为查询对象
		//通过查询解析器解析一个字符串为查询对象
			String f = "content"; //查询的默认字段名,
			Analyzer a = new SimpleAnalyzer();//查询关键字要分词,所有需要分词器
			QueryParser parser = new QueryParser(f, a);
			Query query = parser.parse("content:"+keyWord);
			// * 2 准备IndexSearcher
			Directory d = FSDirectory.open(Paths.get(path ));
			IndexReader r = DirectoryReader.open(d);
			IndexSearcher searcher = new IndexSearcher(r);
			// * 3 使用IndexSearcher传入查询对象做查询-----查询出来只是文档编号DocID
			TopDocs topDocs = searcher.search(query, 1000);//查询ton条记录 前多少条记录
			System.out.println("总命中数:"+topDocs.totalHits);
			ScoreDoc[] scoreDocs = topDocs.scoreDocs;//命中的所有的文档的封装(docId)
			// * 4 通过IndexSearcher传入DocID获取文档
			for (ScoreDoc scoreDoc : scoreDocs) {
				int docId = scoreDoc.doc;
				Document document = searcher.doc(docId);
				// * 5 把文档转换为前台需要的对象 Docment----> Article
				System.out.println("=======================================");
				System.out.println("title:"+document.get("title")
								+",content:"+document.get("content"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

3.高亮显示
依赖

<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-highlighter</artifactId>
    <version>5.5.0</version>
</dependency>
**
 * 高亮:就是对搜索匹配到的关键字,自定义一个样式.
 *   需要一个高亮的pom依赖.
 *   对搜索出的结果再进行一个标识
 * @throws Exception
 */
@Test
public void testIndexSearcherHigh() throws Exception {

    Path pathStr = Paths.get(path);
    Directory directory = FSDirectory.open(pathStr);
    IndexReader indexReader = DirectoryReader.open(directory);//读索引
    //1:创建一个IndexSearcher:从哪里读取索引
    IndexSearcher indexSearcher = new IndexSearcher(indexReader);

    String f = "content";//查询的字段:默认查询的字段
    //词法分析器
    Analyzer analyzer = new SimpleAnalyzer();
    QueryParser queryParser = new QueryParser(f, analyzer);
    String queryCondition = "content:hello";//查询条件
    Query query = queryParser.parse(queryCondition);
    //查询content字段包含java的前10条数据
    //2:使用indexSearcher进行搜索:
    TopDocs topDocs = indexSearcher.search(query, 10);// top n

    //此处加入的是搜索结果的高亮部分
    SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<b><font color='pink'>","</font></b>"); //如果不指定参数的话,默认是加粗,即<b><b/>
    QueryScorer scorer = new QueryScorer(query);//计算得分,会初始化一个查询结果最高的得分
    Fragmenter fragmenter = new SimpleSpanFragmenter(scorer); //根据这个得分计算出一个片段
    Highlighter highlighter = new Highlighter(simpleHTMLFormatter, scorer);
    highlighter.setTextFragmenter(fragmenter); //设置一下要显示的片段

    for(ScoreDoc scoreDoc : topDocs.scoreDocs) { //取出每条查询结果
        Document doc = indexSearcher.doc(scoreDoc.doc); //scoreDoc.doc相当于docID,根据这个docID来获取文档
        //获取content字段:
        String content = doc.get("content");
        System.out.println("没有高亮的:"+content);
        //显示高亮部分
        if(content != null) {
            TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(content));
            //取高亮后的content字段的值
            String summary = highlighter.getBestFragment(tokenStream, content);
            System.out.println("高亮的:"+summary);
        }
    }
}

4.7.API
1.Directory对象 索引目录对象
索引的创建对象,使用的是SimpleFSDirectory
直接使用FsDirectory –系统自动会到后台找对用Directtory处理, 通过open方法

在这里插入图片描述对Document提供的方法

indexWriter.deleteAll(); 删除
indexWriter.deleteDocuments(Term ...term);查询出来 在删除
indexWriter.deleteDocuments(Query ... query); 查询出来 在删除
indexWriter.updateDocuments(Term term,....); 更新

2.Document(行)及IndexableField(列)
当往索引中加入内容的时候,每一条信息用一个Document来表示,Document的意思表示文档,也可以理解成记录,与关系数据表中的一行数据记录类似;
IndexableField表示字段,与关系数据表中的列类似(列数量不定!!),每个Document也由一系列的IndexableField组成,可以理解为数据库的动态列;
使用的是Field也是属于IndexableField下面的:
在这里插入图片描述store属性:表示字段值是否存储,Store.YES表示要存储,而Store.NO则表示不存储;
index属性:表示字段的索引方式,
Tokenized表示根据设定的词法分析器来建立该字段的索引;FALSE,不分词;true要分词。
在这里插入图片描述Store和Index组合使用的适用情况见下图:
在这里插入图片描述5.分词器Analyzer(词法分析器)
分词器:SmartChineseAnalyzer,“极易分词” MMAnalyzer ,或者是“庖丁分词”分词器、IKAnalyzer。推荐使用IKAnalyzer
(1)使用smartchinese分词器

<dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-smartcn</artifactId>
            <version>5.5.0</version>
        </dependency>

(2)IKAnalyzer
5.Query及Searcher
1)单词查询
在这里插入图片描述2)段落搜索
在这里插入图片描述3)通配符搜索
在这里插入图片描述4)模糊搜索
在这里插入图片描述5)临近查询,在段落查询的基础上用“~”后面跟一个1到正无穷的正整数。代表段落中,单词与单词之间最大的间隔数
在这里插入图片描述
6)组合查询
在这里插入图片描述4.8.实战
使用场景:可以记录系统日志查询(自动更新结合springaop、手动生成)
步骤:
1、前台,提供一个“搜索”按钮,点击后定位到搜索页面
2、前台,提供一个新的“搜索”页面,搜索页面里面一个查询表单,查询表单下面放查询内容
注意:前台传递到后台需要串基本数据类的名称.
3、后台,接收查询条件,封装到查询对象
4、后台,把“查询对象”传入Service完成查询
a)使用“查询对象”产出Lucene的Query对象
b)使用Query完成Lucene索引库的查询
5、后台,把结果封装,返回。

5.相关技术点—CXF

5.1异构系统
每个系统所使用的结构、语言都不一样,需要整合在一起
5.2面向服务编程
soa
在这里插入图片描述
webservice是基于http协议与xml技术,并且使用了WSDL描述和soap协议传输的异构系统解决方案
ws的应用程序称为客户端 提供ws的应用程序称为服务端
ws:是一个技术的规范,实现这个规范有:jdk自带功能;第三方开源框架:cxf.
5.3CXF
一个实现ws的实现soa框架
在这里插入图片描述使用步骤:
1.安装cxf
在这里插入图片描述
环境变量的配置: 把cxf的路径配置到path下面;
在这里插入图片描述2.相关依赖

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--cxf版本-->
<cxf-version>3.2.7</cxf-version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf-version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf-version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf-version}</version>
</dependency>

<!--spring环境:只要用来管理bean-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>

3.cxf的配置

<?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:jaxws="http://cxf.apache.org/jaxws"
       xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

    <!--配置成spring的bean
        id="userService"  beanId
        implementor="cn.itsource.service.impl.UserServiceImpl"接口实现类
        address="/HelloWorld"服务地址
        -->
    <jaxws:endpoint id="IMantenanceServiceCXF" implementor="cn.xxx.rpms.service.impl.MantenanceServiceImplCXF" address="/HelloWorld"/>
</beans>

注意在applicationContext.xml引入cxf的xml

<import resource="classpath*:applicationContext-cxf.xml"/>

4.暴露服务

package cn.xxx.rpms.service;

import cn.xxx.basic.service.IBaseService;
import cn.xxx.basic.utils.PageList;
import cn.xxx.rpms.domain.Maintenance;
import cn.xxx.rpms.query.MaintenanceQuery;

import javax.jws.WebService;
IMantenanceServiceCXF
@WebService
public interface IMantenanceServiceCXF extends IBaseService<Maintenance>{
    PageList<Maintenance> queryLimt(MaintenanceQuery maintenanceQuery);
}

package cn.xxx.rpms.service.impl;

import cn.xxx.basic.mapper.BaseMapper;
import cn.xxx.basic.service.impl.BaseServiceImpl;
import cn.xxx.basic.utils.PageList;
import cn.xxx.rpms.domain.Maintenance;
import cn.xxx.rpms.domain.MaintenanceItem;
import cn.xxx.rpms.mapper.MaintenanceItemMapper;
import cn.xxx.rpms.mapper.MaintenanceMapper;
import cn.xxx.rpms.mapper.OptMapper;
import cn.xxx.rpms.query.MaintenanceQuery;
import cn.xxx.rpms.service.IMantenanceService;
import cn.xxx.rpms.service.IMantenanceServiceCXF;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.jws.WebService;
import java.util.List;

@WebService
public class MantenanceServiceImplCXF extends BaseServiceImpl<Maintenance> implements IMantenanceServiceCXF {

    @Autowired
    private MaintenanceMapper maintenanceMapper;
    @Autowired
    private OptMapper optMapper;

    @Autowired
    private MaintenanceItemMapper maintenanceItemMapper;
    @Override
    protected BaseMapper<Maintenance> getMapper() {
        return maintenanceMapper;
    }

    @Override
    public void delete(Long id) {
        Maintenance maintenance = maintenanceMapper.selectByPrimaryKey(id);
        //将维修人员清空
        maintenance.setOpt(null);
        //维修单清空
        List<MaintenanceItem> maintenanceItems = maintenance.getMaintenanceItems();
        for(MaintenanceItem maintenanceItem:maintenanceItems){
            maintenanceItemMapper.deleteByPrimaryKey(maintenanceItem.getItemid());
        }
        maintenance.setMaintenanceItems(null);

        maintenanceMapper.deleteByPrimaryKey(id);

    }
    @Override
    public void update(Maintenance maintenance) {
        //修改明细单的维修员
        Long optid = maintenance.getOptid();
        List<MaintenanceItem> maintenanceItems = maintenance.getMaintenanceItems();
        for(MaintenanceItem maintenanceItem:maintenanceItems){
            maintenanceItem.setOpid(optid);
        }
        maintenanceMapper.updateByPrimaryKey(maintenance);
    }


    @Override
    public PageList<Maintenance> queryLimt(MaintenanceQuery maintenanceQuery) {
        Page<Maintenance> objects = PageHelper.startPage(maintenanceQuery.getPage(), maintenanceQuery.getLimit());
        maintenanceMapper.loadDataByQueryLimt(maintenanceQuery);
        return new PageList<>(objects.getTotal(), objects.getResult());
    }
}

5.服务开启,访问到的暴露出来的服务
在这里插入图片描述6.客服端
6.1相关jar

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--cxf版本-->
<cxf-version>3.2.7</cxf-version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf-version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf-version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf-version}</version>
</dependency>

<!--spring环境:只要用来管理bean-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>

新建模块—>在模块java目录输入指令
wsdl2java -encoding utf-8 -p cn.itsource.client.user http://localhost:80/service/HelloWorld?wsdl
wsdl2java -encoding utf-8 -p cn.xxx.client http://localhost:80/service/HelloWorld?wsdl
命令说明:
wsdl2java 根据wsdl文件生成java文件
-encoding utf-8 编码设置
-p 生成文件的包配置
Classpath下创建文件:applicationContext-cxf-client.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">



    <jaxws:client id="helloClient"
                  serviceClass="cn.xxx.client.IMantenanceServiceCXF"
                  address="http://localhost/service/HelloWorld"/>
</beans>

客服端的applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
    http://www.springframework.org/schema/context  
    http://www.springframework.org/schema/context/spring-context.xsd  
    http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans.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
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <import resource="classpath*:applicationContext-cxf-client.xml"/>

</beans>

客服端 的mvc

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
    http://www.springframework.org/schema/context  
    http://www.springframework.org/schema/context/spring-context.xsd  
    http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans.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
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 开启springmvc对注解的支持 -->
    <mvc:annotation-driven/>

    <!-- 使用默认的静态资源处理Servlet处理静态资源,需配合web.xml中配置静态资源访问的servlet -->
    <mvc:default-servlet-handler/>

    <!-- 自动扫描springmvc控制器 -->
    <context:component-scan base-package="cn.xxx.controller"/>

    <!-- 视图解析器 -->
    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>



    <!-- 配置jackson处理JSON数据 -->
    <bean id="stringConverter"
          class="org.springframework.http.converter.StringHttpMessageConverter">
        <constructor-arg value="UTF-8" index="0"/>
        <property name="supportedMediaTypes">
            <list>
                <value>text/plain;charset=UTF-8</value>
            </list>
        </property>
    </bean>
    <bean id="jsonConverter"
          class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">

    </bean>
    <aop:aspectj-autoproxy />
</beans>

相关controller

package cn.xxx.controller;

import cn.xxx.client.IMantenanceServiceCXF;
import cn.xxx.client.Maintenance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class ClientController {
  @RequestMapping("/get")
  @ResponseBody
    private Maintenance get(Long id){
      System.out.println(id);
      ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext-cxf-client.xml");
      String[] beanDefinitionNames =
              context.getBeanDefinitionNames();
      for (String beanDefinitionName : beanDefinitionNames) {
          System.out.println(beanDefinitionName);
      }
      //从spring环境中获取bean,强转
      IMantenanceServiceCXF helloClient = (IMantenanceServiceCXF) context.getBean("helloClient");
      System.out.println(helloClient.getClass());//动态代理
      Maintenance maintenance = (Maintenance) helloClient.get(id);

      System.out.println(maintenance);//就像调用本地服务一样调用远程服务
      return maintenance;
  }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">



  <display-name>Archetype Created Web Application</display-name>
  <!--解决字符编码问题-->
  <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <!--启动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>
  <!--核心控制器的配置 -->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--启动服务器启动mvc-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:applicationContext-mvc.xml</param-value>
    </init-param>
    <!--启动顺序-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

6.相关技术点—三方登录

登录实现了三方登录(微信登录),即可以扫码登录
6.1实现三方登录准备工作
打开微信开发平台(https://open.weixin.qq.com/):
在这里插入图片描述
使用邮箱进行注册(最好使用企业邮箱,避免使用私人邮箱,后续需要企业的资质认证等,避免你离职后的交接麻烦):

在这里插入图片描述在这里插入图片描述开发者认证
在这里插入图片描述认证成功后设置好回调域
6.2维修三方登录原理
网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统。
在进行微信OAuth2.在进行微信OAuth2.0授权登录接入之前,在微信开放平台注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,可开始接入流程
相关流程:
用户请求三方登录—》微信会拉起二维码----》用户授权登录----》微信会拉起应用或重定向到第三方网站,并且返回临时票据code参数----》网站可以code参数加上AppID和AppSecret等,通过API换取access_token----》通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作
在这里插入图片描述6.3实现步骤
1.请求code(拉起属于自己应用的二维码)
第三方使用网站应用授权登录前请注意已获取相应网页授权作用域(scope=snsapi_login),则可以通过在PC端打开以下链接:
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
若提示“该链接无法访问”,请检查参数是否填写错误,如redirect_uri的域名与审核时填写的授权域名不一致或scope不为snsapi_login。
参数说明
参数 是否必须 说明
appid 是 应用唯一标识
redirect_uri 是 请使用urlEncode对链接进行处理
response_type 是 填code
scope 是 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即
state 否 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验
返回说明
用户允许授权后,将会重定向到redirect_uri的网址上,并且带上code和state参数
redirect_uri?code=CODE&state=STATE
若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数
redirect_uri?state=STATE
请求示例
登录一号店网站应用
https://passport.yhd.com/wechat/login.do
打开后,一号店会生成state参数,跳转到
https://open.weixin.qq.com/connect/qrconnect?appid=wxbdc5610cc59c1631&redirect_uri=https%3A%2F%2Fpassport.yhd.com%2Fwechat%2Fcallback.do&response_type=code&scope=snsapi_login&state=3d6be0a4035d839573b04816624a415e#wechat_redirect
微信用户使用微信扫描二维码并且确认登录后,PC端会跳转到
https://passport.yhd.com/wechat/callback.do?code=CODE&state=3d6be0a4035d839573b04816624a415e
为了满足网站更定制化的需求,我们还提供了第二种获取code的方式,支持网站将微信登录二维码内嵌到自己页面中,用户使用微信扫码授权后通过JS将code返回给网站。
JS微信登录主要用途:网站希望用户在网站内就能完成登录,无需跳转到微信域下登录后再返回,提升微信登录的流畅性与成功率。 网站内嵌二维码微信登录JS实现办法:
步骤1:在页面中先引入如下JS文件(支持https):
http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js
步骤2:在需要使用微信登录的地方实例以下JS对象:
var obj = new WxLogin({
self_redirect:true,
id:“login_container”,
appid: “”,
scope: “”,
redirect_uri: “”,
state: “”,
style: “”,
href: “”
});
参数说明
参数 是否必须 说明
self_redirect 否 true:手机点击确认登录后可以在 iframe 内跳转到 redirect_uri,false:手机点击确认登录后可以在 top window 跳转到 redirect_uri。默认为 false。
id 是 第三方页面显示二维码的容器id
appid 是 应用唯一标识,在微信开放平台提交应用审核通过后获得
scope 是 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可
redirect_uri 是 重定向地址,需要进行UrlEncode
state 否 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验
style 否 提供"black"、"white"可选,默认为黑色文字描述。详见文档底部FAQ
href 否 自定义样式链接,第三方可根据实际需求覆盖默认样式。详见文档底部FAQ
2.拿到通过code拿到token(确认登录,微信返回token)
通过code获取access_token
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
参数说明
参数 是否必须 说明
appid 是 应用唯一标识,在微信开放平台提交应用审核通过后获得
secret 是 应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
code 是 填写第一步获取的code参数
grant_type 是 填authorization_code
返回说明
正确的返回:
{
“access_token”:“ACCESS_TOKEN”,
“expires_in”:7200,
“refresh_token”:“REFRESH_TOKEN”,
“openid”:“OPENID”,
“scope”:“SCOPE”,
“unionid”: “o6_bmasdasdsad6_2sgVt7hMZOPfL”
}
参数说明
参数 说明
access_token 接口调用凭证
expires_in access_token接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新access_token
openid 授权用户唯一标识
scope 用户授权的作用域,使用逗号(,)分隔
unionid 当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段。
错误返回样例:
{“errcode”:40029,“errmsg”:“invalid code”}
刷新access_token有效期
access_token是调用授权关系接口的调用凭证,由于access_token有效期(目前为2个小时)较短,当access_token超时后,可以使用refresh_token进行刷新,access_token刷新结果有两种:

  1. 若access_token已超时,那么进行refresh_token会获取一个新的access_token,新的超时时间;
  2. 若access_token未超时,那么进行refresh_token不会改变access_token,但超时时间会刷新,相当于续期access_token。
    refresh_token拥有较长的有效期(30天),当refresh_token失效的后,需要用户重新授权。
    请求方法
    获取第一步的code后,请求以下链接进行refresh_token:
    https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
    参数说明
    参数 是否必须 说明
    appid 是 应用唯一标识
    grant_type 是 填refresh_token
    refresh_token 是 填写通过access_token获取到的refresh_token参数
    返回说明
    正确的返回:
    {
    “access_token”:“ACCESS_TOKEN”,
    “expires_in”:7200,
    “refresh_token”:“REFRESH_TOKEN”,
    “openid”:“OPENID”,
    “scope”:“SCOPE”
    }
    参数说明
    参数 说明
    access_token 接口调用凭证
    expires_in access_token接口调用凭证超时时间,单位(秒)
    refresh_token 用户刷新access_token
    openid 授权用户唯一标识
    scope 用户授权的作用域,使用逗号(,)分隔
    错误返回样例:
    {“errcode”:40030,“errmsg”:“invalid refresh_token”}
    注意:
    1、Appsecret 是应用接口使用密钥,泄漏后将可能导致应用数据泄漏、应用的用户数据泄漏等高风险后果;存储在客户端,极有可能被恶意窃取(如反编译获取Appsecret);
    2、access_token 为用户授权第三方应用发起接口调用的凭证(相当于用户登录态),存储在客户端,可能出现恶意获取access_token 后导致的用户数据泄漏、用户微信相关接口功能被恶意发起等行为;
    3、refresh_token 为用户授权第三方应用的长效凭证,仅用于刷新access_token,但泄漏后相当于access_token 泄漏,风险同上。

建议将secret、用户数据(如access_token)放在App云端服务器,由云端中转接口调用请求。
3.通过access_token调用接口
获取access_token后,进行接口调用,有以下前提:

  1. access_token有效且未超时;
  2. 微信用户已授权给第三方应用帐号相应接口作用域(scope)。
    对于接口作用域(scope),能调用的接口有以下:
    授权作用域(scope) 接口 接口说明
    snsapi_base /sns/oauth2/access_token 通过code换取access_token、refresh_token和已授权scope
    snsapi_base /sns/oauth2/refresh_token 刷新或续期access_token使用
    snsapi_base /sns/auth 检查access_token有效性
    snsapi_userinfo /sns/userinfo 获取用户个人信息
    其中snsapi_base属于基础接口,若应用已拥有其它scope权限,则默认拥有snsapi_base的权限。使用snsapi_base可以让移动端网页授权绕过跳转授权登录页请求用户授权的动作,直接跳转第三方网页带上授权临时票据(code),但会使得用户已授权作用域(scope)仅为snsapi_base,从而导致无法获取到需要用户授权才允许获得的数据和基础功能。
    接口调用方法可查阅《微信授权关系接口调用指南》
    4.授权后接口调用(UnionID)

先通过用户授权拿到code 和state ---->在通过code发生请求,拿到access_token 和open_id----》在通过二者的拿到用户的信息
1.微信url的工具类的抽取
将访问的常量与地址封装,到时候替换

public class WxConstants {
    public final static String APPID = "wxd853562a0548a7d0";
    //用户授权后微信的回调域名
    public final static String CALLBACK="http://bugtracker.itsource.cn";
    public final static String SCOPE = "snsapi_login";
    public final static String APPSECRET = "4a5d5615f93f24bdba2ba8534642dbb6";
    //微信上获取code的地址
    public final static String CODEURL = "https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
    //微信上获取at的地址
    public final static String ACCESSTOKEURL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
    //微信上获取用户信息的地址
    public final static String USERINFOURL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID"

2.跳转工具类

public class HttpClientUtil {
    // http://bugtracker.itsource.cn/wechat/callback?code=222&state=99
    // http://bugtracker.itsource.cn/wechat/callback    code=222&state=99
    public  static String doGet(String uri){
        //1:创建一个HttpClient的实例
        CloseableHttpClient httpclient = HttpClients.createDefault();
        //2:创建一个get请求实例
        HttpGet httpGet = new HttpGet(uri);
        //请求的响应:
        CloseableHttpResponse response1=null;
        try {
            //3:使用HttpClient的实例执行get请求
            response1= httpclient.execute(httpGet);
            //http请求的状态:404 500 200
            System.out.println(response1.getStatusLine());
            int statusCode = response1.getStatusLine().getStatusCode();
            if(statusCode==200){
              //请求成功:
                HttpEntity entity1 = response1.getEntity();
                String result = EntityUtils.toString(entity1, "utf-8");
                System.out.println(result);
                return result;
            }else{
                //请求失败:自己做自己的业务逻辑
            }

        }catch (Exception ex){
            ex.printStackTrace();
        }
        return null;
    }

请求成功后的回调

@RequestMapping("/callback")
    public String callback(String code, String state, Model model, HttpServletRequest req){
      
 String atUrl =  WeChatConstants.ACCESS_TOKEN.replace("APPID",WeChatConstants.APPID)
                .replace("SECRET",WeChatConstants.SECRET)
                .replace("CODE",code);

        String atJsonStr = HttpClientUtil.doGet(atUrl);
        System.out.println("atJsonStr:"+atJsonStr);
        JSONObject jsonObject = (JSONObject)JSON.parse(atJsonStr);
        String access_token = String.valueOf(jsonObject.get("access_token"));
        String open_id = String.valueOf(jsonObject.get("openid"));
        System.out.println("access_token:"+access_token);
        System.out.println("open_id:"+open_id);

        String userInfoUrl = WeChatConstants.USER_INFO.replace("ACCESS_TOKEN", access_token).replace("OPENID", open_id);
        String userInfo = HttpClientUtil.doGet(userInfoUrl);

        JSONObject userJson = (JSONObject)JSON.parse(userInfo);
        System.out.println(userJson);
        //完成绑定操作
        model.addAttribute("userInfo", userInfo);
        return "main";
    }

维修拉起二维码

<%--引入微信的js支持--%>
<script type="text/javascript" src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
<script type="text/javascript">
    var obj = new WxLogin({
        self_redirect:true,
        id:"login_container",
        appid: "",
        scope: "snsapi_login",
        redirect_uri: "",
        state: "xxx",
        style: "white",
        href: ""
    });
</script>

相关jar’

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>
<dependency>
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpclient</artifactId>
     <version>4.5.2</version>
</dependency>

配置回调地址

配置hosts文件:
127.0.0.1 xxx

注意:把防火墙关闭

7.相关技术点—百度地图API

涉及到还车的百度地图API
在这里插入图片描述将申请的开发者平台验证码进行换掉即可使用

8.相关技术点—shiro权限框架

我们对登录,访问进行了权限的拦截
1.shiro框架
shiro是一个具有会话管理、密码学、身份验证、登录的安全框架
在这里插入图片描述从用户看shiro
在这里插入图片描述shiro内部:
在这里插入图片描述2.shiro的核心对象
在这里插入图片描述在这里插入图片描述流程:
用户登录 将用户的账户与密码存入UsernamePasswordToken—》通过subject去登录----》
shiro在服务启动成功就通过filterChainDefinitionMapFactory设置哪些访问会被拦截
securityManager会根据subject拿到的账户与密码通过realm取做登录认证,如果成功会去数据库读取相应的权限,存入session

  • 5
    点赞
  • 28
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

我就是我,是不一样的烟火

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值