【真香】一个C++后台的SSM总结

前言

看到群博上大家积极的更新博客,惭愧的自己,康康啊康康,怎么能堕落呢。赶紧写博客啊。

老早就知道Spring-SpringMVC-Mybatis的大名了,甚至在小伙伴面试时也了解了一下session/cookie的相关知识,但是一直没有机会自己动手实践一下,感谢母校给了我这样一个宝贵的机会,让我在毕业前真正体验了一把Java web开发的感觉。

作为一个C++后台,一直对这些东西都没什么理解。

师兄说:“想的通,写不通,还是空。”对我来说,如果想都想不通,那不如先写写,写着写着,可能也就想通了。

不得不说,真正写了一周项目后,我的感受就一个。

真香!

至于原因嘛

先立个FLAG,我先去学车,放假了补上。
(科三过了ohohoh)
我觉得最大的两个好处1.方便开发,大大的提升了开发效率2.架构思路清晰,可以说遵循框架的架构设计,让整个项目的架构简洁,美观,可扩展性非常强。

本文的目的

网上SSM的资料超级多,而我这篇文章的目的并不是一篇正统的SSM科普文,想要系统学习Java Web的同学可以点击x了。
这只是自己从一个Java web 0基础小白的总结文,其中概念叙述并不是很正确(并没有认真看书学习)。如果你也是需要快速实现一个小项目,或者带着好奇的心态想看看web开发是啥(当然你需要有一定的其他开发的基础),这篇文章可以让你快速入门。

正文

开发环境

便于操作,开发环境为Linux + IDEA。
IDEA可以说是新手的必备了,一个很重要的tip:IDEA没自动补全的,估计就是你写错了。而Linux则是因为这是我更加熟悉的开发环境。

而IDEA,java环境啥的,请自己准备吧。同时,为了减少学习知识,我采用了手动导jar包,而并没有使用Maven(怎么简单怎么来,Yeah)。

总体架构

我的项目采用的是前后端分离架构,所以总结的是纯后端,并不会操心前端的事。要做的只是接受参数,处理业务->操作数据库,然后将结果以JSON的格式返回。

而到代码层面,则分为Entity,DAO,Service,Crontroller四层。
Entity,实体类,每个实体对应数据库里的一张表。
DAO,这个类都是抽象类,表示一个实体对数据库的操作。
Service,感觉是对DAO层的一次封装,提供服务给更上层的Crontroller
Crontroller,实现业务逻辑的地方,调用Service提供的服务。

开发流程

1.设计数据库
这就是按照业务去设计数据库,建表。
以一个简单的用户表User为例,包含三个字段id(自增主键),name(姓名),passwd(密码)。
2.编写Entity类
每张表对应一个实体类,把表中的字段写成类的属性,然后自动生成getter-setter方法。

对应User表的User类

public class User {
    private int id;
    private String name;
    private String passwd;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }
}

3.编写DAO层
还是以User为例,分为一个抽象类和一个xml文件。抽象类定义接口,xml按照mybatis的语(zi)法(dong)编(bu)写(quan)。

public interface UserDAO {
    public User queryUserByName(String name);
    public int insertUser(User user);
    public List<User> display();
}
<?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="dao.UserDAO">

    <select id="queryUserByName" resultType="entity.User">
        select * from User where name=#{name};
    </select>

    <insert id="insertUser" keyProperty="id" useGeneratedKeys="true" parameterType="entity.User">
        insert into User(name, passwd) values(#{name}, #{passwd});
    </insert>
    <select id="display" resultType="entity.User">
        select * from User;
    </select>

</mapper>

简单说,MyBatis就是将SQL语句转换为成了一个接口,这样我们就不用再像原来那样使用比较原始的方式操作数据库了。
上面的三个接口可以说非常有代表性了。
1.#{}指定参数,很神奇的是MyBatis可以“智能”地找到需要的参数。
2.插入时指定了自增主键
3.返回List<User>,但resultType依然是User。

当然,DAO涉及到数据库,我们还需要一些更多的配置。

mybatis-config.xml

<?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>
    
 <!-- 加载SQL映射文件 --> 
 <mappers>
   <mapper resource="dao/UserDAO.xml"/>

 </mappers>

 </configuration>

还有applicationContext.xml中也有很多相关的

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!-- 配置DB 1.加载驱动文件(这个文件就是将数据库的配置,比如用户密码,也可以直接写死) -->
    <context:property-placeholder location="WEB-INF/db.properties"/>

    <!-- 配置DB 2.配置数据源 -->
        <bean id="jdbcDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="${url}"></property>
        <property name="username" value="xxx"></property>
        <property name="password" value="xxx"></property>
    </bean>
    <!--配置mybatis的会话工厂  -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="jdbcDataSource"></property>
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
    </bean>
    <!--配置组件扫描  -->
    <context:component-scan base-package="controller,dao,entity,Service"></context:component-scan>
    <!--配置mapper扫描  -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer ">
        <property name="basePackage" value="dao"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>
    
    <!--下面就和数据库没啥关系了  -->

    <!--配置视图解析器  -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <!--开始mvc注解扫描  -->
    <mvc:annotation-driven/>
    <!--映射静态资源  -->
    <mvc:resources location="/" mapping="*.html"></mvc:resources>
    <mvc:resources location="/fonts/" mapping="/fonts/**"></mvc:resources>
    <mvc:resources location="/js/" mapping="/js/**"></mvc:resources>
    <mvc:resources location="/css/" mapping="/css/**"></mvc:resources>

</beans>

可以看到我们上面引入了一个db.properties文件,其中有一个属性就是url
那么在db.properties文件就要定义url
url=jdbc:mysql://47.102.199.xxx:3306/kangkang?useUnicode=true&characterEncoding=GBK
我这里使用的是云上的mysql,直接写的是ip+port,注意mysql还要加上指定的database,涉及到中文还要指定编码,不然都是乱码。

4.编写Service层
DAO写好后,就是编写其上一层的Service层,我的理解就是Service可能是实现一些具体的操作?而Controller则是业务逻辑,抽象程度更高
这里依然是User类的例子,我的Service就很简单(逻辑都写Controller里了)

@Service
public class UserService {
    @Autowired
    private UserDAO userDAO;

    public User queryUser(String name) {
        User user = userDAO.queryUserByName(name);
        return user;
    }
    public int insertUser(User user) {
        return userDAO.insertUser(user);
    }
    public List<User> display() {
        return userDAO.display();
    }
}

Service注解->不解释
Autowired注解->同不解释,写就vans。
这里的UserDAO就是DAO层的抽象类,可以看到在Service层我们直接调用接口就行类,非常方便。
5.编写Controller层
以用户注册为例,直接看代码


@Controller //不解释
@RequestMapping("/user") //表示整个类的根路径
@ResponseBody //整个类内的方法都带这个注解,就实现类HTTP那种回复体
public class UserController {
    @Autowired
    private UserService userService; //对应Service层,直接调用接口
    
    
    @RequestMapping("/register") //这个方法的路径就是/user/register
    public String registerUser(@RequestParam("user") String name, @RequestParam("password") String passwd) {
		//因为我们前端请求的Content-Type是application/x-www-form-urlencoded格式(我们前端也low,就没用JSON)。
		//所以这里就用@RequestParam将前端的参数对应到你函数的形参

		//业务逻辑就是简单的,查询不存在就插入,然后结果以JSON格式返回
        String result = null;
        JSONObject resultObject = new JSONObject();
        if (userService.queryUser(name) != null) { //检查是否已经存在用户名
            resultObject.put("result", false);
            resultObject.put("detail", "name is dup");
        } else {
            User newUser = new User();

            newUser.setName(name);
            newUser.setPasswd(passwd);
            userService.insertUser(newUser);
            resultObject.put("result",true);
        }
        result = resultObject.toJSONString();
        return result;
    }
}

OK到这里你的函数就编写完了,前端就可以测试了。
通过在浏览器里输入URL,
比如localhost:8080/user/register?user=kang&passwd=kkk
就可以看返回的结果了。

6.Cookie和Session的那些事
因为登录要维持一个会话,而这里就是用到Cookie和Session了。
简单的说Session,就是会话成功建立后(比如登录成功),维持一个状态,保存了一定的数据,这个状态维持也不用你操心,底层都做好了。
以登录函数为例

    @RequestMapping("/login")
    public String loginUser(HttpSession session, @RequestParam("password") String passwd, @RequestParam("user") String name) {

        String result = null;
        JSONObject resultObject = new JSONObject();
        User user = userService.queryUser(name);
        if (user == null || !passwd.equals(user.getPasswd())) {

            resultObject.put("result", false);
        } else {
            resultObject.put("id", user.getId());
            resultObject.put("result", true);
			
			//将这个会话的用户信息存下,以后想知道这是哪个会话看名字就行了
            session.setAttribute("userName",name);
            session.setAttribute("id", user.getId());

        }
        result = resultObject.toJSONString();
        return result;
    }

我们的需求是网站有些内容是登录后才能查看的,那么如何检测登录呢?
这里可以通过过滤器或者拦截器,我们用的是过滤器,大概意思就是所有指定的调用都会经过过滤器,那么没有建立会话(没登录的)我们拦住它就行。
创建类时选择Filter就行
在这里插入图片描述

//指定你需要检测的路径
@WebFilter(filterName = "LoginFilter",urlPatterns = {"/job/createJob","/job/updateJob"})
public class LoginFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //查看是否保存了userName,也就是是否登录了
        String userName = (String) ((HttpServletRequest) req).getSession().getAttribute("userName");
        if(userName == null){
            //没登录,返回一个错误信息,这里用的是Servlet,enmmm这我也不太懂是啥
            HttpServletResponse response = (HttpServletResponse)resp;
            response.setCharacterEncoding("UTF-8");//设置将字符以"UTF-8"编码输出到客户端浏览器
            response.setHeader("content-type", "text/html;charset=UTF-8");//通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码        }else {
            PrintWriter out = response.getWriter();//获取PrintWriter输出流
            out.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>");
            out.write("please login!!!!");
        }else {
           //登录了,放行
            chain.doFilter(req, resp);

        }
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

最后

项目完整地址
https://github.com/kangyijie5473/JobInfoPlatform(请不要点星星,这个项目太low)

感谢小组同学dela,sillduck,hepangda,fujie的帮助,快速上手一个技术还是有人手把手教最快了,不然只能在无尽的bug中连helloworld都整不明白。。

发布了75 篇原创文章 · 获赞 46 · 访问量 9万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览