2018年11月

QQ截图20181115232109.png
触了很久的vue,也做了几个项目,对于vue这款框架,我们对此非常认可,但是我们也要正确的看待它的缺点,它属于渐进式框架,非常轻量级,也非常适合做spa单页应用,但是在我们的新闻,论坛,商城等需要很多搜索引擎流量的一些站点,我们需要正确做好ssr渲染,能够把vue的短板弥补,为了解决这样的问题,nuxt是我们可以优先考虑的选择。

nuxt是一个基于vue的渲染框架,它学起来非常简单,上手快,在工作中也经常用到,我们可以用一篇文章来快速的入门并且掌握项目的一些技巧。

首先我们需要搭建nuxt的环境,node和vuecli是必不可少的.

node和vuecli的安装我就不多说了,我们直接安装nuxt

输入命令:vue init nuxt/starter

我们就可以下载模板,然后进入目录install一下就ok

然后我们的组件和页面都在page下,我们可以更改

pages/index.vue来输出hello world来实现热加载编译

然后启动服务,等待打包成html : npm run dev

然后我们会在页面上看到我们输入的

hello world


目录介绍

|-- .nuxt // Nuxt自动生成,临时的用于编辑的文件,build
|-- assets // 用于组织未编译的静态资源入LESS、SASS 或 JavaScript
|-- components // 用于自己编写的Vue组件,比如滚动组件,日历组件,分页组件
|-- layouts // 布局目录,用于组织应用的布局组件,不可更改。
|-- middleware // 用于存放中间件
|-- pages // 用于存放写的页面,我们主要的工作区域
|-- plugins // 用于存放JavaScript插件的地方
|-- static // 用于存放静态资源文件,比如图片
|-- store // 用于组织应用的Vuex 状态管理。
|-- .editorconfig // 开发工具格式配置
|-- .eslintrc.js // ESLint的配置文件,用于检查代码格式
|-- .gitignore // 配置git不上传的文件
|-- nuxt.config.json // 用于组织Nuxt.js应用的个性化配置,已覆盖默认配置
|-- package-lock.json // npm自动生成,用于帮助package的统一性设置的,yarn也有相同的操作
|-- package-lock.json // npm自动生成,用于帮助package的统一性设置的,yarn也有相同的操作
|-- package.json // npm包管理配置文件


常用配置选项

我们在开发中经常会遇到端口被占用的情况,这种情况我们可以通过packge.json对端口和ip进行更改。

"config":{
"nuxt":{
  "host":"127.0.0.1",
  "port":"1818"
}

}

在开发我们的多页应用的时候,经常会有一些公用样式来约束我们的标签,我们可以通过一个公共的css来控制样式,我们可以对/assets/css/normailze.css下进行配置

(以下说明来自技术胖博客:http://jspang.com)对webpack设置的说明

配置webpack的loader

在nuxt.config.js里是可以对webpack的基本配置进行覆盖的,比如现在我们要配置一个url-loader来进行小图片的64位打包。就可以在nuxt.config.js的build选项里进行配置。

build: {

loaders:[
  {
    test:/\.(png|jpe?g|gif|svg)$/,
    loader:"url-loader",
    query:{
      limit:10000,
      name:'img/[name].[hash].[ext]'
    }
  }
],
/*
** Run ESLint on save
*/
extend (config, { isDev, isClient }) {
  if (isDev && isClient) {
    config.module.rules.push({
      enforce: 'pre',
      test: /\.(js|vue)$/,
      loader: 'eslint-loader',
      exclude: /(node_modules)/
    })
  }
}

}


nuxt对我们操作路由提供了很大的帮助,它实现了自动装配路由的强大功能,我们只需要按照它的规则来写代码,就可以省配置路由的环节

简要说明以下,nuxt是以目录来做路由的基线的,什么意思呢,大白话来说就是我们在pages目录下建立一个目录为news,在news目录下

建立index.vue,在这个组件中我们就可以通过/news来访问这个组件,那么对于路由之间的参数传递我们该怎么操作呢?

路由配置

我们可以通过<nuxt-link :to="{name:'index'}">点击这里跳转到首页</nuxt-link>

nuxt是不太建议我们拿a标签进行链接跳转,他们提供这样的组件来让我们使用,想必是对nuxt更友好,所以我们经常用nuxt-link来做跳转

这个name就是文件夹名字,它会自动找这个文件夹下的index.vue来展示出来,路由的参数就是可以这样写:

<nuxt-link :to="{name:'index',params:{id:1234}}">

params是一个对象,我们可以在里面同时传入多个参数,在目标组件通过$route.params.具体的键就可以取到对应的值。


nuxt的动态路由和参数校验

我们在nuxt中定义动态路由,通常是以下划线结尾的组件,我们在news文件夹下建立_id.vue的组件
然后在这个组件还是用相同的方法来接受参数。

然后我们更改一下news/index.vue

<template>

<div>

  <h2>News Index page</h2>
  <p>NewsID:{{$route.params.newsId}}</p>
   <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/news/123">News-1</a></li>
    <li><a href="/news/456">News-2</a></li>

</div>
</template>

然后可以看到可以正常接受参数,那我们可以进行对这个参数的校验,我们拥有一个方法

validate ({ params }) {

// Must be a number
return /^\d+$/.test(params.id)

}

我们利用这个正则可以对id这个参数进行校验,如果不是数字就会被驳回,页面会显示404页面。


路由动画效果

我们如何通过nuxt来实现路由之间切换并且带有动画呢?

全局动画

我们在assets/css下建立main.css

在这个css中我们写一些样式

.page-enter-active, .page-leave-active {
    transition: opacity 2s;
}
.page-enter, .page-leave-active {
    opacity: 0;
}

必须按照这样写,前缀务必是.page,然后我们让这个链接定义nuxt.config.js中即可

css:['assets/css/main.css']

然后刷新页面,我们会看到一个隐藏显示过渡的效果。
如果你没有看到效果,得要改成<nuxt-link>

这就是全局动画的使用

而我们的局部动画,是针对局部的组件切换的动画。

我们只需要更改刚刚写的css,page改成随意的名字,然后在组件中定义

transition:'你定义的名字'

然后就会让这个组件有效果。


我们做多页应用经常遇到一些公共的内容,比如大标题等,我们可以通过Nuxt的默认模版和默认布局来实现
它们的区别就是一个需要重启服务器,一个不需要,一个是公用的,一个是每个组件需要引入,复杂程度不一样

Nuxt的默认模版和默认布局

首先我们说默认模板,默认模板只需要在根目录定义一个app.html即可

   <!DOCTYPE html>
<html lang="en">
<head>
   {{ HEAD }}
</head>
<body>
    <p>因卓诶</p>
    {{ APP }}
</body>
</html>

这样每个页面都可以显示因卓诶,需要重启服务器,这就是默认模板,那我们的默认布局就比较麻烦了。

    <template>
  <div>
    <p>因卓诶2</p>
    <nuxt/>
  </div>
</template>

<nuxt/>中就是内容,这样这个组件就有默认的布局,我们可以根据不同的业务需求来更改我们的代码,但是个人不建议

总结:要区分默认模版和默认布局的区别,模版可以订制很多头部信息,包括IE版本的判断;模版只能定制<template>里的内容,跟布局有关系。在工作中修改时要看情况来编写代码。


错误页面和个性meta

当在nuxt中我们输入一个未定义的路由组件,会出现一个错误404页面,我们会通常重写error组件,

在根目录下的layouts文件夹下建立一个error.vue文件,它相当于一个显示应用错误的组件。

首先props接受error,然后判断错误的信息码来判断是什么错误。

设置组件的meta或者标题title我们可以简单地通过路由传参来传递内容,然后在组件中定义一个:

//独立设置head信息

head(){

  return{
    title:this.title,
    meta:[
      {hid:'description',name:'news',content:'This is news page'}
    ]
  }
}

ps:注意:为了避免子组件中的meta标签不能正确覆盖父组件中相同的标签而产生重复的现象,建议利用 hid 键为meta标签配一个唯一的标识编号。
(此话出自技术胖,摘抄)

这样就可以了!对SEO非常有帮助,也是要养成编码优化习惯。


asyncData方法

我们在nuxt中经常用异步来获取数据,首先安装axios这些基本的东西我就不说了

我们可以通过promise来获取一下!这边我们的json链接通过myjson.com自由获取,非常棒的网站!

 asyncData(){
  return axios.get('https://api.myjson.com/bins/8gdmr')
  .then((res)=>{
      console.log(res)
      return {info:res.data}
  })

}

非常简单,通过这样的方法,这个方法是专门nuxt为我们提供异步加载的方法。

我们在学习或者工作中也会用到es7的语法,所以我们来await一下,做一个demo。

 async asyncData(){
  let {data}=await axios.get('https://api.myjson.com/bins/8gdmr')
  return {info: data}

}

其实这个方法也是从技术胖那里学到的,es7还是没接触过,有时间一定好好学习一下!


项目打包和编译

用Nuxt.js制作完成后,你可以打包成静态文件并放在服务器上,进行运行。

在终端中输入:

npm run generate


文章如果有错误,欢迎指出,我的微信meng99huan,转载说明出处因卓诶,谢谢

最近做项目的时候用到了vuex,写了很久的java,写vue还是很生疏,终究起来还是vue的code功底不深,我们直接进入正题,来复习一下vuex的应用做一个简单的数据共享存储。

首先我们需要在vuecli下的store文件夹下定义几个文件。

QQ截图20181107104303.png

目录介绍:
--action.js (异步操作,我们这边没有用到异步,所以里面不用写内容)
--getter.js (用于对属性进行包装,通过getter这个js来获取值)
--index.js (vuex的入口文件)
--mutations-type.js (定义变量类型)
--mutation.js (对属性进行赋值)
--state.js (定义数据对象)

index.js

import Vue from 'vue'

import Vuex from 'vuex'
import * as actions from './action'
import * as getters from './getter'
import state from './state'
import mutations from './mutations'
//引入vuex的报告
import creatLogger from 'vuex/dist/logger'

Vue.use(Vuex);
//创建debug,在开发环境下,因为如果在线上环境,会消耗资源,所以是在开发环境下
const debug=process.env.NODE_ENV !== 'production'

//引入
export default new Vuex.Store({

actions,
getters,
state,
mutations,
strict:debug,
plugins: debug ? [creatLogger()] : []

})

getter.js

//箭头函数的简写,把仓库中的singer对象返回给singer常量

export const singer = state => state.singer

mutations-type.js

export const SET_SINGER = 'SET_SINGER'

mutation.js

import * as types from './mutations-type'

const mutations ={

//通过type来获取常量,
[types.SET_SINGER](state,singer){
    //给仓库中的singer对象附对象(组件中的singer对象给仓库存储起来)
    state.singer=singer
}

}

export default mutations;

store配置结束,我们在main.js中引入store即可

然后我们开始在组件中写代码。

我们需要在组件中定义设置属性

import {mapMutations} from 'vuex'

然后通过展开运算符来定义

...mapMutations({
        setSinger : 'SET_SINGER'
    })

然后通过 this.setSinger(item) ,把item值存储到仓库。

然后我们在另外的组件中去取值,同样要引入import {mapGetters} from 'vuex'

然后通过计算属性拿到singer对象,并且利用钩子函数来打印这个对象

    computed:{
    ...mapGetters([
        'singer'
    ])
},
created(){
    console.log(this.singer);
}

结束,我们就可以很清楚的在控制台打印出了对象和我们的vuex的debug信息。

QQ截图20181107113821.png

经过了一段时间的学习,对ssm已经有了初步的认识,然后也坎坷的做出了增删改查,实际上放假都是在休息或者游戏,所以憋了2天才写出来。

我觉得一个简单的增删改查是满足不了大家的,所以我会尽可能地详细的讲,也会让大家注意我踩的坑,跟着这篇文章,我相信你能快速的搭建ssm框架并且完成相应的业务需求。

业务没有设计maven,所以我们创建xml等操作都是手动完成。

1.准备jar包,ssm的包以及jstl,还有分页插件pagehelper以及sql解释jar。

QQ截图20181105182645.png

注意:jar包没有截图全部,具体的jar下载直接在文章末尾的github上直接下载

2.创建我们的web工程,目录结构如下

QQ截图20181105182808.png

注释:

action:springmvc控制开发
mapping:mybaties映射接口和文件
pojo:业务实体类
service:业务实现类

创建spring,springmvc,mybaties,数据库连接文件,日志文件

spring:

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

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd ">

<!--读取数据库配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>

<!-- 数据库连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="maxActive" value="10" />
    <property name="maxIdle" value="5" />
</bean>

<!-- Mybatis的工厂 -->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <!-- 1) 核心配置文件的位置 -->
    <property name="configLocation" value="classpath:mybaties.config.xml"/>
    <!-- 2)扫描指定目录下的所有Mapper.xml -->
    <property name="mapperLocations" value="classpath:com/ssmall/mapping/*.xml"></property>
</bean>

<!-- 配置自动扫描的包 -->
<context:component-scan base-package="com">


<!-- 扫描时跳过 @Controller 注解的JAVA类(控制器) -->
<context:exclude-filter type="annotation"
        expression="org.springframework.stereotype.Controller" />
</context:component-scan>


<!-- 注解事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>


<!-- 开启注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

springmvc:

<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

<!-- 配置自定扫描的包 -->
<context:component-scan base-package="com" />

<mvc:annotation-driven />
<!-- 配置视图解析器: 如何把 handler 方法返回值解析为实际的物理视图 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"></property>
    <property name="suffix" value=".jsp"></property>
</bean>


<!-- 配置 MultipartResolver -->
<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="defaultEncoding" value="UTF-8"></property>
    <property name="maxUploadSize" value="1024000"></property>    
</bean>    

</beans>

myabites:

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

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

<!-- 类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余 -->
<typeAliases>
    <typeAlias alias="User" type="com.ssmall.pojo.Userpojo" />
</typeAliases>

<!-- 配置分页插件 -->
<plugins>
    <plugin interceptor="com.github.pagehelper.PageHelper">
        <!-- 设置数据库类型Oracle,MySQL,MarinDBName,SQLite,PostareSQL六种数据库 -->
        <property name="dialect" value="mysql" />
    </plugin>
</plugins>

</configuration>

db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/sys?characterEncoding=utf-8
jdbc.username=root
jdbc.password=swq891012

web.xml:

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

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- 1.spring容器 listener -->
<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>
 
<!-- 2.springmvc servlet -->
<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
    </init-param>
</servlet>
 
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
  
<!-- 3.spring 中文乱码 filter -->
<!-- 编码过滤器,解决中文乱码 -->
<filter>
    <filter-name>SpringEncoding</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>
</filter>
<filter-mapping>
    <filter-name>SpringEncoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
 

<welcome-file-list>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>
</web-app>

3.开发mybaties映射接口和mybaties映射xml

接口(所属包mapping):

package com.ssmall.mapping;

import java.util.List;

import com.ssmall.pojo.Userpojo;

public interface UserMapping {

public List<Userpojo> getAll();
public Userpojo getUser(Integer id);
public boolean deleteById(Integer id);
public boolean add(Userpojo user);
public boolean update(Userpojo user);

}

mybaites映射

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

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 为这个mapper指定一个唯一的namespace,namespace的值习惯上设置成包名+sql映射文件名,这样就能够保证namespace的值是唯一的

例如namespace="me.gacl.mapping.userMapper"就是me.gacl.mapping(包名)+userMapper(userMapper.xml文件去除后缀) -->

<mapper namespace="com.ssmall.mapping.UserMapping">

<!-- 在select标签中编写查询的SQL语句, 设置select标签的id属性为getUser,id属性值必须是唯一的,不能够重复 使用parameterType属性指明查询时使用的参数类型,resultType属性指明查询返回的结果集类型 
    resultType="me.gacl.domain.User"就表示将查询结果封装成一个User类的对象返回 User类就是users表所对应的实体类 -->
<!-- 根据id查询得到一个user对象 -->

<select id="getUser" parameterType="int" resultType="com.ssmall.pojo.Userpojo">
    select * from t_user where id=#{id}
</select>
<select id="getAll" resultType="com.ssmall.pojo.Userpojo">
    select * from t_user
</select>
<delete id="deleteById" parameterType="int">
    delete from t_user where id=#{id}
</delete>
<insert id="add">
    insert into t_user(username,password,account) values
    (#{username},#{password},#{account})
</insert>
<update id="update">
    update t_user set username=#{username},password=#{password},account=#{account} where id=#{id}
</update>

</mapper>

注意:这边的查询语句由于使用了分页插件pageHelper,所以无需做变化
1)id要与接口的方法名对应上,并且放在一个包下,命名空间namespace是唯一的,所以建议写映射包名+类名的写法(写的是接口)
2)mybaties映射xml文件名和映射接口文件名要一样,后缀不同即可

4.开发dao层,service层

dao层(接口省略):

package com.ssmall.dao;

import java.util.List;

import javax.annotation.Resource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.stereotype.Repository;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ssmall.mapping.UserMapping;
import com.ssmall.pojo.Userpojo;

@Repository
public class IPublicDaoImpl extends SqlSessionDaoSupport implements PublicDao{


/*super.setSqlSessionFactory(sessionFactory):调用父类方法,将sqlsessionfactory注入进去*/
@Resource
public void setSessionFactory(SqlSessionFactory sqlSessionFactory) {
    super.setSqlSessionFactory(sqlSessionFactory);
}

/**
 * 公共dao层方法
 */
public Userpojo get(int id) {
    
    UserMapping mapper = this.getSqlSession().getMapper(UserMapping.class);
    Userpojo user = mapper.getUser(id);
    return user;
}
//查询数量
public static final int PAGE_SHOW_NUMBER=5;
@Override
public PageInfo<Userpojo> getAll(Integer index) {
    UserMapping mapper = this.getSqlSession().getMapper(UserMapping.class);
    PageHelper.startPage(index, PAGE_SHOW_NUMBER);
    List<Userpojo> all =mapper.getAll();
    //用PageInfo对结果进行包装
    PageInfo<Userpojo> pageInfo = new PageInfo<Userpojo>(all);
    return pageInfo;
}

//查询数据的总页数


@Override
public boolean deleteById(Integer id) {
    UserMapping mapper = this.getSqlSession().getMapper(UserMapping.class);
    return mapper.deleteById(id);
}

@Override
public boolean addUser(Userpojo user) {
    UserMapping mapper = this.getSqlSession().getMapper(UserMapping.class);
    return mapper.add(user);
}

@Override
public boolean updateUser(Userpojo user) {
    UserMapping mapper = this.getSqlSession().getMapper(UserMapping.class);
    return mapper.update(user);
}

}

注意:在我们的查询方法中,返回的不是List集合,而是分页插件提供的类PageInfo,我们通过映射接口取得list可以通过PageInfo的方法转换进行包装,在PageInfo类中有许多我们常用的方法,比如数据库的分页页数,长度等等,非常有利于我们开发,所以在查询的这个方法中我们定义了常量,这个常量就是一页显示多少条,第一个参数index,是第几页

service层:

package com.ssmall.service;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ssmall.dao.PublicDao;
import com.ssmall.pojo.Userpojo;

@Service
public class IUserServiceImpl implements UserService {

@Resource
private PublicDao dao;

//根据ID查询单条
public Userpojo get(Integer id) {
    
    return this.dao.get(id);
}



//查询全部
public PageInfo<Userpojo> getAll(Integer pageNum) {
    return this.dao.getAll(pageNum);
}
//删除单条
public boolean deleteById(Integer id) {
    
    return this.dao.deleteById(id);
}
@Override
public boolean addUser(Userpojo user) {
    
    return this.dao.addUser(user);
}
@Override
public boolean updateUser(Userpojo user) {
    
    return this.dao.updateUser(user);
}
    

}

action层:

package com.ssmall.action;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.github.pagehelper.PageInfo;
import com.ssmall.pojo.Userpojo;
import com.ssmall.service.UserService;

@Controller
public class UserAction {

@Resource
private UserService userService;

/**
 * 查询所有信息
 * 
 * @param null
 * @return
 */
@RequestMapping("/user/all/{index}")
public ModelAndView getUserAll(@PathVariable("index") Integer index) {
    ModelAndView model = new ModelAndView("list");
    PageInfo<Userpojo> all = userService.getAll(index);
    List<Userpojo> list = all.getList();
    model.addObject("allList", list);
    //存储当前索引在域中
    model.addObject("index", index);
    //计算能分多少页
    int pages = all.getPages();
    model.addObject("lastnum", pages);
    return model;
}

/**
 * 根据id查询单条信息
 * 
 * @param id
 * @return
 */
@RequestMapping("/user/get/{id}")
public String getUserById(@PathVariable("id") Integer id) {
    Userpojo userpojo = userService.get(id);
    return "success";
}

/**
 * 根据id删除
 * 
 * @param id
 * @return
 */
@RequestMapping("/deleteById")
public String DeleteById(@RequestParam("id") Integer id) {
    // 执行删除
    boolean deleteById = userService.deleteById(id);
    // 删除成功后查询
    return "redirect:/user/all/1";
}

/**
 * 新增用户
 * 
 * @param user
 * @return
 */
@RequestMapping("/user/addUser")
public String addUser(Userpojo user) {
    userService.addUser(user);
    return "redirect:/user/all";
}

// 新增用户的跳转方法
@RequestMapping("/user/addready")
public String addReady(Model model) {
    model.addAttribute("itemForm", "form");
    // 添加用户之后,在请求域中添加一个判断添加或者修改页面的依据
    // 根据这个依据,可以通过jstl共用form.jsp页面
    return "form";
}

/**
 * 修改用户
 * 
 * @param user
 * @return
 */
@RequestMapping("/update")
public String update(Userpojo user){
    userService.updateUser(user);
    return "redirect:/user/all/1";
}
@RequestMapping("/updateById")
public String updateReady(@RequestParam("id") Integer id,Model model) {
    Userpojo userpojo = userService.get(id);
    model.addAttribute("userlist", userpojo);
    return "form";
}

}

注意:
主要难点还是查询的方法,只要理解了查询的方法,其他的增删改都是非常之简单。

主要的是我们的jsp页面,我们大量的用到了jsp页面,在WEB-INF/views下很多jsp,其中我们的增加的表单和修改的表单都是form.jsp,我们通过action设置的请求域值来区分当前是增加操作还是修改操作。

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>

<base href="<%=basePath%>">

<title>My JSP 'form.jsp' starting page</title>

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">    
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->

</head>

<body>

    <c:if test="${itemForm != null}">
      <form action="user/addUser" method="post">
  </c:if>
  <c:if test="${itemForm == null}">
      <form action="update" method="post">
  </c:if>
       <input type="hidden" name="id" value="${userlist.id}">
        用户名:<input type="text" name="username" value="${userlist.username}">
        <br>
        密码:<input type="password" name="password" value="${userlist.password}">
        <br>
       详情:<input type="text" name="account" value="${userlist.account}">
       <br>
       
       <c:if test="${itemForm != null}">
           <input type="submit" value="添加">
       </c:if>
       
       <c:if test="${itemForm == null}">
           <input type="submit" value="修改">
       </c:if>
       
  </form>

</body>
</html>

下面就是我们的list展示页面,上一页和下一页,都是利用el表达式来编码,也巧妙地用了if判断,来在首页隐藏上一页,末页隐藏下一页避免了逻辑错误

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%

String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
        + path + "/";

%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>list</title>

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--

<link rel="stylesheet" type="text/css" href="styles.css">
-->

</head>

<body>

<a href="user/addready">添加用户</a>
<table>
 <thead>
   <tr>
     <th>id</th>
     <th>用户</th>
     <th>密码</th>
     <th>详情</th>
     <th>操作</th>
    </tr>
 </thead>
 <tbody>
  <c:forEach items="${requestScope.allList}" var="list">
     <tr>
         <c:if test="${requestScope.allList==''}">
             <td>暂无记录</td>
         </c:if>
         <td>${list.id}</td>
         <td>${list.username}</td>
         <td>${list.password}</td>
         <td>${list.account}</td>
         <td><a href="deleteById?id=${list.id}">删除</a></td>
         <td><a href="updateById?id=${list.id}">修改</a></td>
     </tr>
     </c:forEach>
 </tbody>
</table>
<a href="user/all/1">首页</a>
<c:if test="${index != 1}">
    <a href="user/all/${index-1}">上一页</a>
</c:if>
<c:if test="${index != lastnum}">
    <a href="user/all/${index+1}">下一页</a>
</c:if>
    <a href="user/all/${lastnum}">末页</a>

</body>
</html>

好了,我们的整个整合就结束了:

源码下载地址,bug都测试完了,没有任何问题,欢迎下载demo:

https://github.com/1018715564/ssm-CRUD 下载地址