当前位置: 首页 > news >正文

做网站重要标签seo都用在哪些网站

做网站重要标签,seo都用在哪些网站,wordpress产品页布局,做网站的意义项目介绍: 定位: 专门为餐饮企业(餐厅、饭店)定制的一款软件商品 分为: 管理端:外卖商家使用 用户端(微信小程序):点餐用户使用。 功能架构: &#xff08…

项目介绍:

定位:

        专门为餐饮企业(餐厅、饭店)定制的一款软件商品

分为:

        管理端:外卖商家使用

        用户端(微信小程序):点餐用户使用。

功能架构:

(体现项目中的业务功能模块)

技术选型:

(展示项目中使用到的技术框架和中间件等)

环境搭建

整体架构:

前端:

        管理端使用nginx,使用已经打包好的前端代码,并且Nginx的配置文件中已经配置了反向代理,通过此配置可以将前端请求转发到后端服务。

        用户端之后再做介绍

后端:

后端框架:

  

1.sky-common子模块中存放的是一些工具类,可以供其他模块使用

2.sky-pojo子模块中存放的是一些entity(实体类),DTO,VO

3.sky-server子模块中存放的是配置文件、配置类、拦截器、controller、service、mapper、启动类等

版本控制

        使用Git进行版本控制

数据库:

前后端联调:

        使用nginx反向代理:

nginx反向代理:

好处:

使用方法:

接口文档:

前后端分离开发流程:

设计阶段:

Apifox:

        Apifox是设计阶段使用的工具,管理和维护接口。

开发阶段:

Swagger:

        Swagger是在开发阶段使用的框架,帮助后端开发人员做后端的接口测试

介绍:

使用方式:

1.

2.

3.

常用注解:

管理端业务功能编写:

登录功能:

        完善登录功能使用MD5对数据加密

员工管理:

添加员工:

        添加员工时通过ThreadLocal获取执行人id和创建人id

ThreadLocal介绍:

        并且客户端发起的每一次请求都是一个单独的线程,这样就满足使用ThreadLocal的条件。

ThreadLocal常用方法:

员工分页查询:

        调整LocalDataTime类型数据响应回去的格式

        推荐第二种,只需要一次编码就可以调整全部指定内容

操作过程:

1.新建一个对象映射器:

/*** 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]*/
public class JacksonObjectMapper extends ObjectMapper {public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";//public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";public JacksonObjectMapper() {super();//收到未知属性时不报异常this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);//反序列化时,属性不存在的兼容处理this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);SimpleModule simpleModule = new SimpleModule().addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))).addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))).addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT))).addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))).addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))).addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));//注册功能模块 例如,可以添加自定义序列化器和反序列化器this.registerModule(simpleModule);}
}

2.在配置类中添加如下代码:

    /*** 扩展MVC框架的消息转换器* @param converters*/@Overrideprotected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {log.info("开始扩展消息转换器");//创建一个消息转换器对象MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();//设置对象转换器,可以将java对象转为json对象converter.setObjectMapper(new JacksonObjectMapper());//将自己的转换器放入spring MVC框架的容器中,并放到0索引位置,排到第一个,这样一定会使用它converters.add(0, converter);}

公共字段自动填充:

枚举类:

/*** 数据库操作类型*/
public enum OperationType {/*** 更新操作*/UPDATE,/*** 插入操作*/INSERT}

自定义注解:

/*** 自定义注解,用于标识需要进行公共字段自动填充的方法*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {/*** 枚举类 自定义数据库操作类型insert和update操作* @return*/OperationType value();}

自定义切面类:

/*** 自定义切面,实现公共字段自动填充处理逻辑*/
@Aspect
@Component
@Slf4j
public class AutoFillAspect {/*** 切入点*/@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")public void autoFillPointCut() {}/*** 前置通知,为公共字段赋值*/@Before("autoFillPointCut()")public void autoFill(JoinPoint joinPoint) {log.info("开始进行公共字段填充...");//获取到当前被拦截方法上的数据库操作类型MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解OperationType operationType = autoFill.value();//获得数据库操作类型//获取到当前被拦截方法的参数--实体对象Object[] args = joinPoint.getArgs();Object entity = args[0];//准备赋值的数据LocalDateTime now = LocalDateTime.now();Long currentId = BaseContext.getCurrentId();//根据当前不同的操作类型,为对应的属性通过反射来赋值if(operationType == OperationType.INSERT) {try {Method setCreateTime = entity.getClass().getMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);Method setCreateUser = entity.getClass().getMethod(AutoFillConstant.SET_CREATE_USER, Long.class);Method setUpdateTime = entity.getClass().getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser = entity.getClass().getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);setCreateTime.invoke(entity,now);setCreateUser.invoke(entity,currentId);setUpdateTime.invoke(entity,now);setUpdateUser.invoke(entity,currentId);} catch (Exception e) {e.printStackTrace();}} else if(operationType == OperationType.UPDATE) {try {Method setUpdateTime = entity.getClass().getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser = entity.getClass().getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);setUpdateTime.invoke(entity,now);setUpdateUser.invoke(entity,currentId);} catch (Exception e) {e.printStackTrace();}}}}

给mapper层的insert和update数据库操作类型添加自定义的注解:

        @AutoFill(OperationType.UPDATE)或@AutoFill(OperationType.INSERT)

注意点:

        ·在菜品分页查询部分,可能传来的参数:status状态在动态SQL里只能判断其为null,不能加上and status = '',这样会一直读取不到它,具体原因不清楚。

        ·<set>标签下的<if>标签中的内容记得加逗号

操作Redis:

        想要了解Redis的基础知识及使用方法可以参考作者另一边文章《Java_中间件——Redis》

Redis的Java客户端:

        下面我们使用Spring Data Redis来操作Redis

Spring Data Redis使用方式:

配置类RedisTemplate:

@Configuration
@Slf4j
public class RedisConfiguration {@Beanpublic RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {log.info("开始创建redis模板对象...");RedisTemplate redisTemplate = new RedisTemplate();//设置redis连接工厂对象redisTemplate.setConnectionFactory(redisConnectionFactory);//设置redis key的序列化器redisTemplate.setKeySerializer(new StringRedisSerializer());return redisTemplate;}}

代码演示:

    @Autowiredprivate RedisTemplate redisTemplate;@Testpublic void testRedisTemplate() {System.out.println(redisTemplate);//操作字符串ValueOperations valueOperations = redisTemplate.opsForValue();//操作HashHashOperations hashOperations = redisTemplate.opsForHash();//操作ListListOperations listOperations = redisTemplate.opsForList();//操作setSetOperations setOperations = redisTemplate.opsForSet();//操作有序集合ZSetOperations zSetOperations = redisTemplate.opsForZSet();}/*** 操作字符串类型的数据*/@Testpublic void testStirng() {// set get setex setnxredisTemplate.opsForValue().set("city","北京");String city = (String) redisTemplate.opsForValue().get("city");System.out.println(city);redisTemplate.opsForValue().set("code","6562",60, TimeUnit.SECONDS);redisTemplate.opsForValue().setIfAbsent("lock","1");redisTemplate.opsForValue().setIfAbsent("lock","2");}/*** 操作哈希类型的数据*/@Testpublic void testHash() {//hset hget hdel hkeys hvalsHashOperations hashOperations = redisTemplate.opsForHash();hashOperations.put("100","name","xiaobai");hashOperations.put("100","age","20");String name = (String) hashOperations.get("100", "name");System.out.println(name);Set keys = hashOperations.keys("100");System.out.println(keys);List values = hashOperations.values("100");System.out.println(values);hashOperations.delete("100","age");}/*** 操作列表类型的数据*/@Testpublic void testList() {// lpush lrange rpop llenListOperations listOperations = redisTemplate.opsForList();listOperations.leftPushAll("mylist","a","b","c");listOperations.leftPush("mylist","d");List mylist = listOperations.range("mylist", 0, -1);System.out.println(mylist);listOperations.rightPop("mylist");Long size = listOperations.size("mylist");System.out.println(size);}/*** 操作集合类型的数据*/@Testpublic void testSet() {// sadd smembers scard sinter sunion sremSetOperations setOperations = redisTemplate.opsForSet();setOperations.add("set1","a","b","c");setOperations.add("set2","b","c","d");Set set1 = setOperations.members("set1");System.out.println(set1);Long size = setOperations.size("set1");System.out.println(size);Set intersect = setOperations.intersect("set1", "set2");System.out.println(intersect);Set union = setOperations.union("set1", "set2");System.out.println(union);setOperations.remove("set1","a","b");}/*** 操作有序集合类型的数据*/@Testpublic void testZSet() {// zadd zrange zincrby zremZSetOperations zSetOperations = redisTemplate.opsForZSet();zSetOperations.add("zset1","a",10);zSetOperations.add("zset1","b",11);zSetOperations.add("zset1","c",9);Set zset1 = zSetOperations.range("zset1", 0, -1);System.out.println(zset1);zSetOperations.incrementScore("zset1","c",10);zSetOperations.remove("zset1","a","b");}/*** 通用命令操作*/@Testpublic void testCommon() {// keys exists type delSet keys = redisTemplate.keys("*");System.out.println(keys);Boolean name = redisTemplate.hasKey("name");Boolean set1 = redisTemplate.hasKey("set1");for (Object key : keys) {DataType type = redisTemplate.type(key);System.out.println(type.name());}redisTemplate.delete("mylist");}

店铺营业状态设置:

        基于Redis的字符串来进行存储

        

        1表示营业,0表示打样

代码演示:

管理端设置营业状态、获取营业状态

@RequestMapping("/admin/shop")
@RestController("adminShopController")
@Slf4j
@Api(tags = "店铺相关接口")
public class ShopController {public static final String KEY = "SHOP_STATUS";@Autowiredprivate RedisTemplate redisTemplate;/*** 设置店铺的营业状态* @param status* @return*/@PutMapping("/{status}")@ApiOperation("设置营业状态")public Result setStatus(@PathVariable Integer status) {redisTemplate.opsForValue().set(KEY,status);log.info("设置当前营业状态为:{}",status == 1 ? "营业中" : "打烊中");return Result.success();}@GetMapping("/status")@ApiOperation("管理端获取营业状态")public Result<Integer> getStatus() {Integer status = (Integer) redisTemplate.opsForValue().get(KEY);log.info("当前的营业状态为:{}",status == 1 ? "营业中":"打烊中");return Result.success(status);}}

用户端获取营业状态

@RequestMapping("/user/shop")
@RestController("userShopController")
@Slf4j
@Api(tags = "店铺相关接口")
public class ShopController {public static final String KEY = "SHOP_STATUS";@Autowiredprivate RedisTemplate redisTemplate;@GetMapping("/status")@ApiOperation("用户端获取营业状态")public Result<Integer> getStatus() {Integer status = (Integer) redisTemplate.opsForValue().get(KEY);log.info("当前的营业状态为:{}",status == 1 ? "营业中":"打烊中");return Result.success(status);}}

HttpClient

使用HttpCilent需要导入依赖:

(如果导入了阿里云OSS的依赖就不需要导入了,因为这个依赖中已经包含了这个依赖)

核心API:

发送请求步骤:

代码演示:

    /*** 测试通过HttpClient发送GET方式的请求*/@Testpublic void testGET() throws Exception {//创建HttpClient对象CloseableHttpClient httpClient = HttpClients.createDefault();//创建请求对象HttpGet httpGet = new HttpGet("http://localhost:8080/user/shop/status");//发送请求,接收响应结果CloseableHttpResponse response = httpClient.execute(httpGet);//解析结果//获取服务端返回的状态码int statusCode = response.getStatusLine().getStatusCode();System.out.println("服务端返回的状态码为:" + statusCode);//获取服务端返回数据HttpEntity entity = response.getEntity();String body = EntityUtils.toString(entity);System.out.println("服务端返回的数据为:" + body);//关闭资源response.close();httpClient.close();}/*** 测试通过HttpClient发送GET方式的请求*/@Testpublic void testPOST() throws Exception {//创建HttpClient对象CloseableHttpClient httpClient = HttpClients.createDefault();//创建请求对象HttpPost httpPost = new HttpPost("http://localhost:8080/admin/employee/login");JSONObject jsonObject = new JSONObject();jsonObject.put("username", "admin");jsonObject.put("password", "123456");StringEntity entity = new StringEntity(jsonObject.toString());//指定请求编码方式entity.setContentEncoding("UTF-8");//指定数据格式entity.setContentType("application/json");httpPost.setEntity(entity);//发送请求CloseableHttpResponse response = httpClient.execute(httpPost);//解析返回结果int statusCode = response.getStatusLine().getStatusCode();System.out.println("响应码为:" + statusCode);HttpEntity entity1 = response.getEntity();String body = EntityUtils.toString(entity1);System.out.println("响应数据为:" + body);//关闭资源response.close();httpClient.close();}

用户端微信小程序开发:

小程序目录结构:

主体:

页面:

微信登录过程:

Redis缓存菜品、套餐

原因:

        使用数据库一直查找会导致系统响应慢、用户体验差。所以使用Redis缓存。

缓存菜品:

实现思路:

Spring Cache:

常用注解:

                                                                                                                     (cacheName::key)↑

@Cacheable注解在方法执行前会通过动态代理,代理出一个Controller对象,然后判断缓存中是否有数据,如果有,则直接返回缓存数据,不再执行方法,如果没有,就会通过反射来调用方法。

删除全部:

Spring Task

定位:

        定时任务框架

cron表达式:

        注意:日和周只能一个填数值一个填?

        使用Spring Task对超时订单和一直配送中的订单进行处理

WebSocket

介绍:

应用场景:

        ·视频弹幕

        ·网页聊天

        ·体育实况更新

        ·股票基金报价实时更新

实现步骤:

       

         使用WebSocket来完成来单提醒和客户催单功能。

设计:

Apache POI

介绍:

应用场景:

创新点:

        1.用户端根据分类id查看菜品:通过在service、mapper层添加获取在售(status=1)商品/套餐方法,替代通过创建实体类对象进行list方法查找,将查询时间由5~17ms变为4~7ms。

        2.将工作台订单数据使用redis存储,实时更新。

http://www.dinnco.com/news/5168.html

相关文章:

  • 申报课题所需的网站怎么做歌尔股份砍单
  • 做集群网站百度直播推广
  • 杭州营销型网站建设旺道seo优化软件怎么用
  • 顺德网站建设7starrygoogle全球推广
  • 做网站软件frontpageseo优化按天扣费
  • 宁波高端网站建设搜一搜排名点击软件
  • dedecms做网站网络营销论坛
  • 哈尔滨优化网站排名seo实战培训
  • 旅游业网站建设网页设计软件dreamweaver
  • 别人做的网站百度网站验证外链平台有哪些
  • wordpress页面获取最新文章湖南专业seo优化
  • 做网站发布win10系统优化工具
  • 360算互联网大厂吗网站搜索优化
  • 合肥建设管理学校网站网页设计素材网站
  • 做羞羞事网站网络软文广告
  • 成都企业网站设计长沙网站推广智投未来
  • 如何做网站赚流量钱企业品牌推广营销方案
  • 网站开发查询关键词搜索指数
  • 网站哪家做的好关键词推广优化外包
  • 丰台网站建设百度知道问答平台
  • 软件测试工程师是干嘛的宁波seo网络推广外包报价
  • wordpress首页聚合模块seo关键技术有哪些
  • 辛集专业网站建设电脑培训零基础培训班
  • 网站建设常用工具怎么建网站详细步骤
  • 广西建设工程协会网站查询网站优化推广软件
  • 淄赌博做网站竞价推广渠道
  • 网站设计的价格广州网站排名优化报价
  • 网站建设0doit长春seo优化企业网络跃升
  • 长沙好博网站建设有限公司海外销售平台有哪些
  • 珠海网站开发排名教育培训机构营销方案